为了更好的说明,举一个很常见的例子:
function getData(data) {
return new Promise((resolve, reject) => {
if (data === 1) {
setTimeout(() => {
resolve('getdata success')
}, 1000)
} else {
setTimeout(() => {
reject('getdata error')
}, 1000)
}
})
}
window.onload = async () => {
let res = await getData(1)
console.log(res) //getdata success
}
这样写可以正常打印getdata success
但是如果我们给getData传入的参数不是1,getData会返回一个reject的Promise,而这个地方我们并没有对这个错误进行捕获,则会在控制台看见这样一个鲜红的报错Uncaught (in promise) getdata error
捕捉错误,首先想到的就是“踹一脚”:
window.onload = async () => {
try {
let res = await getData(3)
console.log(res)
} catch (error) {
console.log(res) //getdata error
}
}
看似问题已经被解决,但是如果我们有一堆请求,每一个await
都需要对应一个trycatch
,那就多了很多垃圾代码。或许我们可以用一个trycatch
将所有的await
包起来,但是这样就很不方便对每一个错误进行对应的处理,还得想办法区分每一个错误。
因为返回的是一个Promise,那我们首先想到的就是.then()
和.catch()
,于是很快就能写出以下代码:
window.onload = async () => {
let res = await getData(3).then(r=>r).catch(err=>err);
console.log(res) //getdata error
}
这样看起来比“踹一脚”高大上一点了……
上面那种方法是有一定问题的,如果getData()
返回是resolve
,res
则是我们想要的结果,但是如果getData()
返回是reject
,res
则是err
,这样错误和正确的结果混在一起了,显然是不行的。
window.onload = async () => {
let res = await getData(3)
.then((res) => [null, res])
.catch((err) => [err, null])
console.log(res) // ["getdata error",null]
}
这种方式有的类似error first
的风格。这样可以将错误和正确返回值进行区分了。但是这种方式会让每一次使用await
都需要写很长一段冗余的代码,因此考虑提出来封装成一个工具函数:
function awaitWraper(promise) {
return promise.then((res) => [null, res])
.catch((err) => [err, null])
}
window.onload = async () => {
let res = await awaitWraper(getData(3))
console.log(res) // ["getdata error",null]
}
好多了,就先这样吧。