Promise
- es6推出的新的更好的异步编程解决方案
- 可以在异步操作启动后或完成后,在指定回调函数得到异步结果数据
- promise的链式调用可以解决嵌套回调的回调地狱问题
- promise对象的三种状态
- pengding(初始状态)
- fulfilled(成功状态)
- rejected(失败状态)
- Promise
- Promise是一个构造函数,用于创建promise实例对象
- Promise构造函数必须接受一个实参,也就是执行器函数,该执行器函数会被同步执行
- 执行器函数接受2个实参
- resolve:可以将当前promise状态改为成功
- reject:可以将当前promise状态转为失败
- 执行器函数接受2个实参
- promise.then
- 该函数最多接受2个实参,数据类型为函数
- 如果前面promise状态为成功,触发第一个回调,否则触发第二个
- 总是返回一个新的promise
- 新的promise的结果由then指定回调的结果决定
- 该函数最多接受2个实参,数据类型为函数
- 扩展
- 如何让.than的回调返回成功
- 返回值不是promise对象
- 返回成功的promise
- 如何让.then的回调返回失败
- 报错
- 返回失败的promise
- 如何让.than的回调返回成功
- promise.all([promise1,promise2])
- 批量发送多个异步请求
- 全部成功才返回成功的promise
- 一个失败,就返回失败的promise
- promise.race([promise1,promise2])
- 批量发送多个异步请求,谁先回来用谁
async/await的基本概念
promise的语法糖,简化promise对象的使用,不用再使用then/catch来指定回调- 用同步的方式来执行异步操作的效果
await相当于promise.then- try/catch可捕获异常,相当于
promise.catch await之后的代码都会被放在promise的.then的成功回调中,一定会返回一个全选的promise
async
语法:在函数开头添加async即可
async有什么用?
- 可以让该函数返回一个promise,如果函数有返回值,async会用Promise.resolve()包裹并返回
async function fn() {
console.log('async'); // async
return 'then';
}
fn().then((res) => {
console.log(res) // then
})
await
语法:[返回值] = await 表达式
await操作符用于等待一个Promise对象,只能在异步函数async function中使用
await 会阻塞当前代码的执行,等待 Promise 处理完成
await不能单独使用,会报错
await后跟成功的promise或非promise对象,则返回成功的promise
回调地狱问题
如何实现回调地狱?
- 多个串联的异步操作就会导致回调地狱 我们可以用定时器去简单的模拟一下回调地狱
// 1秒后打印1,2秒后打印2,3秒后打印3
setTimeout(() => {
console.log(1);
setTimeout(() => {
console.log(2);
setTimeout(() => {
console.log(3);
}, 3000);
}, 2000);
}, 1000);
可以看到,每多一个异步操作,代码就会向右缩进,代码的可读性会非常差,串联的少还好,串联的多的话,整体就会很混乱
使用Promise去解决回调地狱问题
function log123(){
return new Promise((resolve,reject)=>{ // 执行器函数,接收2个参数
// resolve 可以将当前promise状态改为成功
// reject 可以将当前promise状态改为失败
setTimeout(()=>{
console.log(1)
resolve(2) // 返回成功的promise并携带参数2
},1000)
})
}
log123().then((value)=>{ // value接收参数
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(value)
resolve(3) // 返回成功的promise并携带参数3
},2000)
})
}).then((value)=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(value)
return '时间到!'
},3000)
})
}).then((res)=>{
console.log(res)
})
可以看到,代码不会一直向右缩进,逻辑分明,代码可读性好
使用async/await解决回调地狱问题
var log = function(time){
return new Promise((resolve,reject)=>{
return setTimeout(()=>{
console.log(time/1000)
resolve()
},time)
})
}
async function log123(){
await log(1000)
await log(2000)
await log(3000)
return '时间到!'
}
log123().then((res)=>{
console.log(res);
})
可以看到,比起.then的链式调用,async/await是不是更加简洁明了呢?
捕获错误
Promise.catch()
async.await中的try/catch