【问题标题】:Asynchronous exception not handled by Promise [duplicate]Promise 未处理异步异常 [重复]
【发布时间】:2018-10-15 19:31:33
【问题描述】:

深入研究 Promises,我发现了一些让我困惑的东西。然而,我意识到发生了什么,并决定在这里分享给可能遇到它的其他人。


我有以下 JavaScript:

new Promise(function (resolve, reject) {
    foo();

    setTimeout(function () {
        resolve();
    }, 400);
}).catch(function (err) {
    console.log('Caught it:', err.message);
});

当我运行它时,我得到:

抓住它:foo 没有定义

这是预期的结果。但是,如果我尝试像这样在setTimeout 回调中调用foo()

new Promise(function (resolve, reject) {
    setTimeout(function () {
        foo();
        resolve();
    }, 400);
}).catch(function (err) {
    console.log('Caught it:', err.message);
});

我明白了:

ReferenceError: foo is not defined
    at Timeout._onTimeout (C:\Users\Hristiyan\Desktop\promise.js:3:13)
    at tryOnTimeout (timers.js:224:11)
    at Timer.listOnTimeout (timers.js:198:5)

问题:为什么我没有得到相同的结果?为什么用catch() 定义的处理程序不处理错误?我的意思是,错误发生在同一个代码块下?

【问题讨论】:

  • "错误出现在同一个代码块下?" - 不,传给new Promise的回调和传给setTimout的回调是两个不同的函数跨度>
  • 同意。我的意思是它视觉上在同一个代码块中,这误导了我。不久之后,我记得“视觉上”没有任何意义。

标签: javascript exception promise


【解决方案1】:

发生这种情况的原因是错误发生在一个单独的调用堆栈中,没有任何东西可以捕获它。

在第一个例子中,错误发生在 Promise 解析器中,它是 Promise 提供的一个函数。然后,Promise 可以捕获错误。如果每个数字代表更深一层的堆栈,它将看起来像这样:

  1. [主要]
  2. 承诺(捕获)
  3. 解析器(抛出)

Resolver 抛出错误,它沿着堆栈向上传播,并被 Promise 捕获。


在第二个示例中,错误发生一段时间后,在这种情况下 - 在 400 毫秒后,当 Promise 的调用堆栈早已消失并无错误地完成执行时。比如:

  1. [主要]
  2. 承诺
  3. 解析器

*400 毫秒后*

  1. setTimeout 处理程序(抛出)(上面没有任何东西可以捕获)

所以错误发生在另一个调用堆栈上,上面没有任何东西可以捕获。即使它在 Promise 的代码块下,它也不在它的 调用堆栈 中。因此,为了使代码按预期工作,需要一个 catch 块来捕获错误。当被捕获时,我们通过调用它的reject 处理程序来通知 Promise:

new Promise(function(resolve, reject) {
  setTimeout(function() {
    try {
      foo();
    } catch (e) {
      return reject(e);
    }

    resolve();
  }, 400);
}).catch(function(err) {
  console.log('Caught it:', err.message);
});

【讨论】:

    猜你喜欢
    • 2014-09-28
    • 1970-01-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2014-06-24
    相关资源
    最近更新 更多