【问题标题】:Why doesn't Promise catch error thrown by async operation? [duplicate]为什么 Promise 不能捕获异步操作抛出的错误? [复制]
【发布时间】:2016-02-12 14:07:48
【问题描述】:

给定以下代码:

var fs = require('fs');

var asyncErrorPromise = new Promise(function(resolve) {
  fs.readFile('does/not/exist.blah', function(fileError, content) {
    if (fileError) throw fileError;
    resolve(content);
  });
});

asyncErrorPromise
  .then(function(content) {
    console.log('content received: ' + content);
  })
  .catch(function(err) {
    console.log('error received: ' + err.name);
  });

我希望抛出的fileError(因为我尝试加载的文件不存在)将被 Promise 捕获并汇集到.catch() 语句中。所以最后我会得到这个输出:error received: ENOENT

但是,当我运行此代码时,我得到的是以下内容:

    if (err) throw err;
             ^

Error: ENOENT: no such file or directory, open 'does/not/exist.blah'
    at Error (native)

所以错误没有被捕获:它像往常一样抛出,就好像它在 Promise 之外一样。

为什么会这样?

我能找到的关于 Promises 的所有内容都更关注被默默吞下的错误,而不是这个问题,当你不想要它时它实际上会抛出!

我应该如何在这里实现我的意图?我需要使用 try-catch 语句和 reject 处理程序吗?

【问题讨论】:

  • 正如您提到的,您需要捕获并拒绝/推迟承诺。任何未捕获的异常都将由引擎处理并停止脚本。
  • 你为什么会catch这个错误?直接拒绝
  • 你使用什么承诺库?在 ES6 中,新的 Promise 构造函数中抛出的错误应该隐式拒绝该 Promise,因此假设 Promise 实现是 ES6 兼容的,您的代码应该可以工作。
  • 可能是因为错误是在异步回调中引发的。如果您将其作为测试之外的内容,它可能会起作用。我会听从其他评论者的建议,直接拒绝错误。
  • 行为预期的,这不是错误。由于它是异步的,因此您将丢失 process.on('uncaughtException') 处理程序中的错误上下文。要保留上下文,您必须使用 Domain 之类的东西,其中 Domain 对象在处理程序中处理错误。

标签: javascript error-handling promise es6-promise


【解决方案1】:

您无法使用 Promise 捕获异步回调函数中抛出的错误,因为它的上下文将会丢失。在您使用 Node 的情况下,您将失去 process.on('uncaughtException') 处理程序中的错误上下文,并且回调将作为其自己的事件在事件队列中运行,具有自己的上下文和范围。

使用promise,正确的解决方案是reject包装promise。

另一种方法是使用Domain 对象(Domain documentation),但它正在等待弃用。使用domain,您可以维护上下文并为您的错误注册一个处理程序,如下所示。

var domain = require('domain');

var d = domain.create();

d.on('error', function(err){
    //Do something with your error
});

d.run(function(){
    //Run your async code that might throw error
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-10
    • 2022-08-19
    • 2021-05-13
    • 2011-11-22
    • 2020-09-28
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多