全部 / 前端 / 技术 · 2022年4月4日 0

39 – Async/Await:错误处理

Promises 允许我们通过 then 中的错误处理模块或者 catch 模块来处理错误。Async/await 有相近的策略。

await 与 catch 一起使用

我们使用 await 一个异步的函数,通常情况下 await 操作符是与 Promise 一起使用的,而且只能再 async 函数内部。Async 函数提供了 promises 所以我们就可以使用 catch 块来处理异常。

const myPromise = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject("We ran into an error");
        }, 2000);
    });
}

const main = async () => {
    const response = await myPromise().catch((err) => {
        console.log(err); // We ran into an error
    })
}

main();

myPromise 2秒钟后 reject 并打印出一条信息,当我们在等待 promise 结果的时候,我们可以在其后增加 catch 来处理错误。

当调用 async 函数时,使用 catch

当我们调用 async 函数时,可以在其后添加 catch。

const myPromise = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject("We ran into an error");
        }, 2000);
    });
}

const main = async () => {
    const response = await myPromise();
}

main().catch((err) => {
    console.log(err); // We ran into an error
});

因为 main 是一个 async 函数且返回一个 promise ,所以我们可以使用 catch 连一起。使用 catch 不错但有一个缺点,它会捕获所有错误而不单单是 myPromise 引起的。

使用高阶函数

我们可以使用 catch 来捕获错误,但假设你项目中有许多 async 函数,为每一个添加 catch 会令人厌烦但你有不得不加,该怎么办?

这时候就需要使用高阶函数,它就是把一个函数作为输入然后输出另一个函数。

const myPromise = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject("We ran into an error");
        }, 2000);
    });
}

const main = async () => {
    const response = await myPromise();
}

const handleError = (err) => {
    console.log(err); // We ran into an error
}

const addingErrorHandler = (fn, errorHandler) => {
    return function() {
        fn().catch(errorHandler);
    }
}

const mainFunctionWithErrorHandler = addingErrorHandler(main, handleError);

mainFunctionWithErrorHandler();

我们添加了三个新方法:

  1. handleError 为一个标准的错误处理函数。
  2. addingErrorHandler 为一个高阶函数,一个函数作为入参同时为该函数添加错误处理。
  3. mainFunctionWithErrorHandler 为 main 函数经过高阶函数处理后能处理异常的函数。

因为例子仅仅处理了一个 main 函数,你可能会感觉添加太多的函数。但我们可以在大项目中通过高阶函数处理不计其数的 async 函数。

使用 try/catch 函数

JavaScript 为我们添加了 try/catch 快来处理异常,同样可以应用在 async/await 上:

const myPromise = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject("We ran into an error");
        }, 2000);
    });
}

const main = async () => {
    try {
        await myPromise(); // try this code
    } catch (err) { // if it throws an error execute the catch block
        console.log(err); // We ran into an error
    }
}

main();

try/catch 是最简单易懂的方式,但在大型项目中我还是喜欢使用高阶函数来处理 async/await 的异常。