javascript我觉得印象深刻的两大特点,单线程和异步,单线程不说了,今天来说下异步吧,这星期我碰到的一个问题,async/await中promise返回reject报错的问题,这是我以前没有留意到的,异步编程步步都是坑,正常的思维方式应该是同步的,而异步思维没经过训练,很容易犯错,我想啊,promise用async,await优化,不仅是为了更优雅的书写,和阅读,通过优化把异步代码写成同步,也是为了更加符合人正常的思维方式吧
本文的叙述路线:
先从es5的异常捕获开始
-------->再到es6Pomise()异常的处理
------>最后来谈谈通过async,await优化promise后reject的问题(这是重点)
ES5的异常捕获:
正常的异常捕获:
try {
throw new Error(3)
} catch(e) {
console.log(e)
}
这是ok的,但是如果try中出现了异步代码呢?
try {
setTimeout(function() {
throw new Error("error")
}, 1000)
} catch(e) {
console.log(e)
}
可以看到,并没有捕获到
原因:
以上例子中第二个try catch捕获不到错误,因为try catch是同步的
,执行到setTimeout时把它放到了异步任务队列里
(setTimeout是异步的)没有立即执行setTimeout就往下走了
,同步任务执行完再回头把异步任务队列里的setTimeout回调函数拿出来执行就报错了。
要捕获到异常,必须在throw new Error的直接外层
用try catch包起来才行:
setTimeout(() => {
try {
throw new Error("error")
} catch(e) {
console.log(e);
}
}, 1000);
ES6 promise方式的错误捕获:
这是异步任务完成调用resolve的做法:
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("ok")
}, 1000)
})
}
fn()
.then(res => {
console.log(res)
})
这是异步任务失败调用reject的捕获异常方法
:
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("error")
}, 1000)
})
}
fn()
.catch(err => {
console.log(err)
})
最重要的部分来了
ES6通过async,await优化promise时的异常捕获:
先来看问题,通过async,await的方式去优化promise,只能接收到成功resolve()的结果
,对于reject()的结果是会报错的
先看下正常resolve() 的情况:正常的
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("ok")
}, 1000)
})
}
async function go() {
let res = await fn()
console.log(res)
}
go()
改成reject()返回结果:发现报错了
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("error")
}, 1000)
})
}
async function go() {
let res = await fn()
console.log(res)
}
go()
解决async/await中的promise返回错误reject的问题,及错误捕获:
方式一:
async/await已经把异步代码优化成了同步代码,同步代码可以通过try,catch捕获到异常
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("error")
}, 1000)
})
}
async function go() {
try{
let res = await fn()
}catch(e){
console.log(e)
}
}
go()
方式二:
通过返回一个pending状态的结果,中断promise链的方式处理错误
function fn() {
return new Promise((resolve, reject) => {
setTimeout(() => {
//reject("error")
return new Promise(() => {
}) //中断promise链
}, 1000)
})
}
async function go() {
let res = await fn()
console.log(e)
}
go()
此时res什么都没接收到,不会出现reject报错的问题了