“捕获”如何在原生承诺链中工作

How does the 'catch' work in a native Promise chain?

本文关键字:承诺 工作 原生 捕获      更新时间:2023-09-26

在Chrome或Firefox的控制台标签上尝试这段代码

var p = new Promise(function(resolve, reject) {
    setTimeout(function() {
        reject(10);
    }, 1000)
})
p.then(function(res) { console.log(1, 'succ', res) })
.catch(function(res) { console.log(1, 'err', res) })
.then(function(res) { console.log(2, 'succ', res) })
.catch(function(res) { console.log(2, 'err', res) })

结果将是

1 "err" 10
2 "res" undefined

我尝试过许多其他例子,但似乎第一个then()返回了一个始终解决且永不拒绝的承诺。我已经在Chrome 46.0.2490.86和Firefox 42.0上尝试过这个。为什么会这样?我以为then()catch()可以多次连锁?

就像在同步代码中一样:

try { 
    throw new Error();
} catch(e) {
    console.log("Caught");
}
console.log("This still runs");

处理异常运行的代码将运行 - 这是因为异常是一种错误恢复机制。通过添加该捕获,您表示错误已处理。在同步情况下,我们通过重新抛出来处理这个问题:

try { 
    throw new Error();
} catch(e) {
    console.log("Caught");
    throw e;
}
console.log("This will not run, still in error");

承诺的作用类似:

 Promise.reject(Error()).catch(e => {
      console.log("This runs");
      throw e;
 }).catch(e => {
      console.log("This runs too");
      throw e;
 });

作为提示 - 永远不要拒绝非Error,因为您会丢失很多有用的东西,例如有意义的堆栈跟踪。

为什么会这样?我以为 then(( 和 catch(( 可以多次链接?

@Benjamin是对的,+1,但换句话说,这些是规则:

  • 如果多次添加then,则会链接应按顺序调用的方法,直到引发异常。then链中的异常必须由then后声明的catch处理。如果then后没有catch,将触发此错误:Uncaught (in promise) Error(…)
  • 如果多次添加catch,则会链接出现问题时应调用的方法(在前面的then函数中(。但是,仅当第一个catch重新引发异常时,才会调用链中的第二个,依此类推。
  • 当触发catch时,链将在catch之后声明的下一个then恢复。