目录
4、回调地狱:在回调函数中再嵌套回调函数的情况称为回调地狱(是实现代码顺序执行的一种操作方式)
一、Promise对象
1、回调函数
当一个函数作为参数传入到另外一个函数,并且该函数不会立即执行;当满足某个条件时才执行该函数
function fn(){
console.log('山海')
}
setTimeout(fn,3000) //fn就是回调函数
2、同步任务
在主线程队列中,只有前一个任务完成后才会执行下一个任务
3、异步任务
不进入主线程队列,而是进入异步队列,前一个任务完成与否不影响后一个任务的执行(不阻塞后续任务执行的任务)
setTimeout(function (){
console.log('执行了回调函数')
},3000)
console.log(111)
// 111
// 执行了回调函数
如果按照代码编写的顺序,应该先输出“执行了回调函数”,再输出“111”。但实际输出为并不是。这种不阻塞后面任务执行的任务就叫做异步任务。
4、回调地狱:在回调函数中再嵌套回调函数的情况称为回调地狱(是实现代码顺序执行的一种操作方式)
setTimeout(function(){
console.log('日日复月月');
setTimeout(function(){
console.log('月月复年年');
setTimeout(function(){
console.log('年年复此生')
},1000)
},2000)
},3000)
// 日日复月月
// 月月复年年
// 年年复此生
这种回调函数中嵌套回调函数的情况就叫做回调地狱。回调地狱就是为是实现代码顺序执行而出现的一种操作,
(1)代码的可读性差、可维护性差
(2)代码的扩展性差
5、回调地狱的解决方法
(1)promise对象
(2)async和await函数
6、关于Promise对象
(1)是一个原生的JavaScript对象,是一种异步编程的解决方案,通过一个回调,避免更多的回调
(2)三个状态:pending(初始状态)、resloved(操作成功)、rejected(操作失败)
(3)简单说Promise就是一个容器,里面保存着某个未来才会结束的事件 (通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息
(4)Promise详解
Promise 状态发生改变,就会触发.then()里的响应函数处理后续步骤.
Promise 状态一经改变,不会再变.
Promise 实例一经创建,执行器立即执行
(5)用法:
① 构造函数有两个参数:resloved和rejected,都是回调函数
② resloved函数:异步操作成功后调用,并将异步操作的结果传递出去
③ rejected函数:异步操作失败后调用,将失败的信息传递出去
④ .then():接收resloved函数传递过来的信息
⑤ catch():接收rejected函数传递过来的信息
function fn(str){ //str='日日复月月'
//创建Promise对象
let p = new Promise(function(resolve,reject){
let flag = true;
setTimeout(function(){ //模拟异步调用
if(flag){ //模拟异步调用成功
resolve(str) //将str通过resolve传递出去 ---- resolve('日日复月月')
}else{ //模拟异步调用失败
reject("操作失败") //将失败的信息通过reject传递出去
}
})
})
return p;
}
fn('日日复月月').then((data)=>{ //.then接收resolve(str)传回来的信息
console.log(data); //data=('日日复月月')
return fn('月月复年年');
}).then((data)=>{
console.log(data); //data=('月月复年年')
return fn('年年复此生')
}).then((data)=>{
console.log(data) //data=('年年复此生')
}).catch((err)=>{
console.log(err)
})
// 日日复月月
// 月月复年年
// 年年复此生
二、async和await函数
1、async用来修饰函数:表示函数是一个异步函数
2、await用来修饰函数
表示等待被修饰的函数的运行结果出来后,再执行后续的操作。必须在async修饰的函数中使用,不能单独使用
var sleep = function(time){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('盛开又凋零')
},time);
})
}
var start = async function(){
console.log('雨来雁去斜雾细雨')
await sleep(3000).then(data=>{
console.log(data) //data='盛开又凋零'
})
console.log('一期一遇几度光阴')
}
start()
// 雨来雁去斜雾细雨
// 盛开又凋零
// 一期一遇几度光阴
3、使用async/await基本规则
(1)await关键字只能在使用async定义的函数中使用
(2)await后面可以直接跟一个 Promise实例对象(可以跟任何表达式,更多的是跟一个返回Promise对象的表达式)
(3)await函数不能单独使用
(4)await可以直接拿到Promise中resolve中的数据
function fn(str){ //str='日日复月月'
//创建Promise对象
let p = new Promise(function(resolve,reject){
let flag = true;
setTimeout(function(){ //模拟异步调用
if(flag){ //模拟异步调用成功
resolve(str) //将str通过resolve传递出去 ---- resolve('日日复月月')
}else{ //模拟异步调用失败
reject("操作失败") //将失败的信息通过reject传递出去
}
})
})
return p;
}
async function test(){
let s1 = await fn('雨来雁去斜雾细雨')
let s2 = await fn('盛开又凋零')
let s3 = await fn('一期一遇几度光阴')
console.log(s1,s2,s3)
}
test()
// 雨来雁去斜雾细雨 盛开又凋零 一期一遇几度光阴
注意:(1)可以直接获取Promise对象的resolve传递的信息,不需要使用.then
(2)使用try...catch来捕获Promise对象的reject传递的异步操作失败的信息
4、promise和async/await区别
(1)promise是ES6,async/await是ES7
(2)async/await相对于promise来讲,写法更加优雅
(3)reject状态
①promise错误可以通过catch来捕捉,建议尾部捕获错误
②async/await既可以用.then又可以用try-catch捕捉