0

最近我在调试一段异步 NodeJS 代码时遇到了非常令人沮丧的事情:我认为肯定会被捕获的异常try..catch正在泄漏,导致async_foo函数外部出现未处理的 promise 错误。

async function async_foo() {
    try {
        await some_library.async_bar('some illegal argument');
    } catch (err) {
        console.error(err); // <- Whether this is called depends on async_bar's implementation !
    }
}

从那以后,我了解到,由于 async..await 是如何通过 Promises 实现的,因此在 async JS 中有许多种方法可以让自己陷入困境,但仍然:

无论嵌套异步代码是如何实现的,是否有可能以绝对绝对始终处理嵌套异步代码错误的方式编写您的异步 JS 代码?基于库的解决方案很重要。

4

2 回答 2

1

无论嵌套异步代码是如何实现的,是否有可能以绝对绝对始终处理嵌套异步代码错误的方式编写您的异步 JS 代码?基于库的解决方案很重要。

不它不是。编写不佳的异步代码可能会抛出一个普通的异步回调,该回调由事件循环从一个空的堆栈帧调用,而您无法使用try/catch. 这是一个简单的例子:

setTimeout(() => {
    throw new Error("thrown from a setTimeout callback");
}, 10);

除了全局使用类似的东西之外,没有办法从回调本身外部捕获该异常:

process.on('uncaughtException', function(err) {
    // log and shut down
});

但是到那时,您对真正发生的事情或如何修复内部状态没有任何背景。可能有打开的文件或套接字,可能有适当的事件处理程序。可以分配其他资源。可能会以不好的方式留下内部状态。此时通常的建议是关闭服务器并重新启动。

实际上,你不想到这里。您希望通过知道如何正确清理和处理错误的代码在上下文中捕获错误,坦率地说,确实没有任何替代品。


幸运的是,使用 Promise 正确编写的代码,.then()and .catch()or awaitandtry/catch将把被拒绝的 Promise 传播到调用链上,只要你想要它去。但是,要做到这一点,必须正确编写代码。不链接或返回承诺的写得不好的代码仍然会造成即使使用承诺也不能正确处理异常或拒绝的情况。

于 2022-02-18T10:04:47.133 回答
0

无论嵌套异步代码是如何实现的,是否有可能以绝对绝对始终处理嵌套异步代码错误的方式编写您的异步 JS 代码?

不,而且可能永远不会。Node.js 文档很好地解释了它:

由于 throw 在 JavaScript 中的工作原理,几乎没有任何方法可以安全地“从中断的地方重新开始”,而不会泄漏引用或创建其他类型的未定义的脆弱状态。响应抛出错误的最安全方法是关闭进程。

库负责解决每种类型的错误并安全地处理它们并在它们发生时将它们传播给消费者(如果需要)。

您可以使用已弃用的domain模块,但在这种情况下它可能对您没有帮助,因为“没有'error'为未处理的 Promise 拒绝发出任何事件。”。

于 2022-02-18T09:36:59.040 回答