如何优雅地捕捉 async await 错误

2034 25 0 技术 2021-02-16

ES7的新语法async await是基于Promise封装成的语法糖,将异步代码直接书写成同步代码,使得读写看起来更优雅,更直观,这是终极的异步方案。但是目前很多新手会有一些误区,比如错误捕捉。

新手误区

模拟下日常使用场景,例如进行一次请求:

(async function () {
    const res = await axios.get('/test');
    console.log(res);
})()

当请求成功之后会将结果赋值给res,后面就打印出请求结果;但是当请求失败的话,这个错误我们是无法捕捉的,这是很多人的使用误区。

错误捕捉

如果我们要捕捉await的错误,按照规范是应该使用try...catch...方法,如下例:

(async function () {
    try {
        const res = await axios.get('/test');
    }
    catch(err) {
        console.log(err);
    }
})()

本来使用async await的初衷是优雅,这样书写就违背初衷了,导致多了一层嵌套,而且要使用代码块内定义变量符letconst也必须放到错误捕捉外面,增加了代码量。

更优雅的错误捕捉

那有没有方法可以让异步代码彻彻底底变成同步代码一样捕捉错误呢?当然是有啦!

因为await后面是一个Promise对象,我们可以对这个对象做一个封装结果的函数,函数内将这个对象resolvereject状态返回的结果进行处理后统一成一个数组结果并return,使用的时候使用解构数组用以获取结果。

听着可能有点绕,简单的封装代码为例:

// 统一封装函数
const unity = promise => {
    return promise.then(res=>[null, res]).catch(err=>[err]);
}

// 使用
(async function () {
    let [err, res] = await unity(new Promise((resolve, reject) => {reject('error')}));
    if (err !== null) {
        console.log(err);   //error
        return false;
    }
    console.log(res);
})()

这种风格类似于Golang语言,这样写法对于错误的捕捉就会显得优雅多了。

© 2020 peal.cc 粤ICP备2020133024号