这周学习了promise中异常的捕获和阮一峰的ECMAScript 6入门的第18章《async 函数》。
上周学习了promise,当遇到复杂的调用时promise看起来都是一堆then,语义不明。await相对于promise的优点是异步看起来更同步,代码简洁。async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
例1:setTimeout模拟接口调用,用promise封装,返回一个随机数,如果小于1,则等待一段时间后返回成功,否则返回失败
init (t) {
return new Promise((resolve, reject) => {
let timeOut = Math.random() * 2
console.log(timeOut)
setTimeout(() => {
if (timeOut < 1) {
console.log('call resolve()...')
resolve('c')
} else {
console.log('call reject()...')
reject('s')
}
}, t)
})
},
test1 () {
this.init(3000).then((res) => {
console.log('then-resolve',res)
},(err) =>{
console.log('then-reject',err)
}).catch((err) => {
console.log('catch',err)
})
运行结果1:返回小于1的数,代表成功,走.then()第一个函数获得resolve返回的数据
f0.5176093896232428
call resolve()...
then-resolve c
运行结果2:返回大于1的数,代表有异常,走.then()第二个函数获得reject返回的异常信息
1.6043320880936638
call reject()...
then-reject s
运行结果3:如果.then()只有一个函数的话,异常由catch捕获
1.546962129917373
call reject()...
catch s
总结:(1)如果没有reject,catch捕获的是所有的异常,有reject的时候,reject捕获的是promise的异常,catch捕获的是then和reject里面的异常。
(2)new一个promise的时候,resolve和reject都需要,因为要告知调用方成功和失败的结果。调用一个promise的时候,只需要关心then,catch,finally。
例2:同例1,如果小于1,则等待一段时间后返回秒数+1,否则返回失败
async test2 () {
try {
let res1 = await this.init(3000)
let res2 = await this.init(res1)
console.log(res2)
} catch (err) {
console.log(err)
}
},
运行结果1:res2 等待res1有了返回值后返回结果,res2的值是基于res1的值的。
0.5757553919256684
call resolve()...
0.0895437557499501
call resolve()...
3002
运行结果2:如果在init开始的时候抛一个异常,res1下面的代码不再执行,直接catch返回错误信息。
总结:(1)promise优点:解决多层嵌套,可以链式调用;promise缺点:看起来都是一堆then,语义不明;await优点:异步看起来更同步,代码简洁。
(2)第一个await有异常的时候,后续代码不再执行,如果想要继续执行后面的代码,第一个await用try/catch包起来。