javascript中异步操作的异常怎么处理?

javascript中用try catch捕获处理异常,比如:

try{
    throw new Error('fail');
}catch (e){
    console.log(e);
}

只需要把可能出现异常的代码包裹在try模块里面,然后在catch模块里面处理异常就可以了。
但是如果try模块里面是通过异步操作抛出的异常,异常就不能正常捕获到。比如:

try{
    setTimeout(()=>{
        throw new Error('fail');
    },1000);
}catch (e){
    console.log(e);
}

异常没有捕获到,控制台报错信息如下:

clipboard.png

想问的问题就是,javascript中如何捕获处理异步抛出的异常呢?

阅读 7.5k
3 个回答

如果是异步的异常,那就在异步代码里捕获异常撒。贴代码:

    setTimeout(()=>{
        try{
            throw new Error('fail');
        }catch (e){
            console.log(e);
        }
    },1000);

感谢 @艾纹 指出错误。我这里把一个知识点记混了,Promise 的 catch 可以捕捉同步异常,不能捕捉异步代码中的异常。所以下面的回答不能解决题主的问题,只能让大家了解 Promise 和 async/await。

关于处理 JS 错误的问题,可以看看JavaScript 里如何正确的进行错误处理

到目前为止,暂时没有想到不改变异步代码而直接通过语法来捕捉异常的办法,浏览器中可以使用 window.onerror 来处理,参考 @艾纹 回答中的评论。


使用 ES6 可以用 Promise 的方式来处理。如果直接使用 ES5,Promise 库也很多,比如 Bluebird。

function doSomething() {
    return new Promise((resolve, reject) => {
        // 同步代码中的 throw 可以被捕捉到
        throw new Error("synchronized fail");
    
        // 异步代码中的 throw 不能被 Promise 的 catch 捕捉到
        // setTimeout(() => {
        //     throw new Error("fail");
        // }, 1000);
    });
}

doSomething()
    .then(() => {
        // do something right
    })
    .catch(e => {
        // e is rejected object
        // or a thrown error object
    });

关于Promise,可以参考

然后,如果用上了 ES2017 的 async/await,你又可以使用 try ... catch 了,就像这样

async function doSomething() {
    // 由于 async/await 是通过 Promise 实现的,
    // 所在道理相同

    // 同步代码异常可以被捕捉到
    throw new Error("synchronized fail");

    // 异步代码中抛出的异常不可被 try { await } 捕捉
    // return new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         throw new Error("fail");
    //     }, 1000);
    // });
}

async function main() {
    try {
        await doSomething();
    } catch (e) {
        // do while error occuring
    }
}

main();

关于 async/await 可以参考理解 JavaScript 的 async/await

使用promise或async处理异步代码,自带的异常处理内容

推荐问题
宣传栏