You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

同一Promise的catch方法为何被调用两次?不同链式写法的输出差异解析

同一Promise的catch方法为何被调用两次?不同链式写法的输出差异解析

别急,咱们一步步拆解这两个例子的核心区别,其实关键在于你调用.catch()的对象到底是不是同一个Promise,以及Promise的状态不可变性这两个关键点。

第一个例子:给同一个原始Promise绑定多个独立的catch回调

const promise = Promise.reject();

promise
  .catch(() => console.log(1));
  
promise
  .catch(() => console.log(2));

// Output:
// 1
// 2

这里的核心逻辑是:你两次调用.catch(),都是直接绑定到同一个处于rejected状态的原始Promise上。

Promise有个核心特性:状态一旦确定(resolved/rejected)就永远不会改变。原始的promise已经是rejected状态了,不管你给它绑定多少个catch(或者then)回调,这些回调都会被依次触发——因为Promise会永久记住自己的最终状态,所有后续添加的回调都会基于这个状态执行。

所以第一个catch执行后,原始promise的rejected状态并没有任何变化,第二个catch作为独立绑定的回调,自然也会被调用,于是就输出了1和2。

第二个例子:链式调用的catch绑定的是全新Promise

const promise = Promise.reject();

promise
  .catch(() => console.log(1))
  .catch(() => console.log(2));

// Output:
// 1

这里的逻辑完全不同,因为**.catch()方法本身会返回一个全新的Promise**。我们拆解下具体执行流程:

  1. 原始promise是rejected状态,触发第一个.catch()回调,执行console.log(1)
  2. 这个第一个.catch()的回调函数没有返回rejected的Promise,也没有抛出错误,所以它会默认返回一个处于resolved状态的新Promise
  3. 后面的第二个.catch(),其实是绑定在这个新的resolved Promise上的——而resolved状态的Promise不会触发catch回调,所以第二个catch根本不会执行,最终只输出1。

你之前的误解在于以为第一个catch会改变原始Promise的状态,但实际上Promise的状态是不可变的,链式调用里的catch操作的是新生成的Promise,而非原始的那个。

备注:内容来源于stack exchange,提问作者Pavel Orlov

火山引擎 最新活动