我应该避免在 Node js 上的每个 async/await 中使用 try catch 吗?

Jul*_*dez 7 javascript node.js async-await jestjs

这是我在单元测试时遇到的一个设计问题。\n让我们深入研究示例:

\n

想象一下:

\n
async function foo()\xc2\xa0{\n    try {\n        return apiCall()\n    }\n    catch (e) {\n        throw new CustomError(e);\n    } \n}\n\n\n\nasync function bar() {\n    return foo()\n}\n\n\n\nasync function main() {\n    try {\n        await bar()\n    }catch(e) {\n        console.error(e)\n    }\n}\n\nmain()\n
Run Code Online (Sandbox Code Playgroud)\n

我们在这里看到什么?唯一没有 try-catch 块的函数是 bar。\n但是如果 foo 失败,它应该被 main catch 捕获。

\n

虽然像这样进行单元测试

\n
describe(\'testing bar\', () => {\n    it(\'foo should throw\', () => {\n        foo.mockImplementantion(() => { throw new CustomError(\'error\')});\n        bar()\n        .then((result) => console.log(result))\n        .catch((err) => { exepect(err).toBeInstanceOf(CustomError)}) // this is what we are testing\n    })\n})\n
Run Code Online (Sandbox Code Playgroud)\n

我们看到的输出是控制台中记录了未处理的承诺拒绝。

\n

所以,我的问题是......即使我知道会main()捕获错误,我是否应该在所有异步函数中使用 try-catch 块?

\n

Est*_*ask 3

try..catch如果函数能够从错误中恢复、执行日志记录等副作用或重新抛出更有意义的错误,则可能有必要。

IfCustomError比可能apiCall抛出 thentry..catch必要的错误更可取,否则则不会。还有一个问题foo是它只处理同步错误。为了处理被拒绝的承诺,应该是这样return await apiCall(),这是一个已知的陷阱async

未捕获的拒绝是不需要的,它们目前会导致UnhandledPromiseRejectionWarning并且预计会在未来版本中导致 Node 崩溃。最好在顶层以有意义的方式处理错误,因此main需要捕获错误。这可以委托给process uncaughtRejection事件处理程序,但它可能有益于保持不应达到的额外错误处理级别。

我们看到的输出是控制台中记录了未处理的承诺拒绝。

这不应该发生。拒绝需要通过测试来处理。上面解释了一个可能的失败点,foo可以返回原始错误,apiCall而不是CustomError在没有正确模拟的情况下,这将不符合预期并导致catch(). 另一个失败点是测试有不受约束的承诺,因为它没有返回,测试总是通过。

使用 Promise 的异步测试应该始终返回 Promise。这可以通过使用来改进async..awaitfoo是的async,它应该总是返回一个承诺:

it('foo should throw', async () => {
    foo.mockImplementantion(() => { return Promise.reject(new CustomError('error')) });
    await expect(bar()).rejects.toThrow(CustomError);
})
Run Code Online (Sandbox Code Playgroud)

现在,即使foo模拟失败(如果它们是在所示的同一模块中定义的,则foo模拟不会影响)并拒绝某些不是的东西,这将被断言。barbarCustomError