You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RSVP Promises疑问:父Promise为何等待非链式内部Promise?

嘿,我来帮你搞清楚这个RSVP.js的问题~

先把你的代码贴出来方便分析:

new RSVP.Promise(function (resolve) {
  console.log('1');
  var p = new RSVP.Promise(function (innerResolve) {
    setTimeout(function () {
      console.log('3');
      innerResolve();
    }, 5000);
  });
  resolve(p);
}).then(function () {
  console.log('2');
});

你的预期和实际行为的差异

你原本以为会先输出1,紧接着输出2,5秒后再输出3——觉得内部的Promise p会被当作普通值直接处理,外部Promise会立即resolve触发then回调。但实际运行下来,应该是先输出1,然后等5秒后输出3,最后才是2,对吧?

问题出在哪:Promise同化的规则

这里的核心是Promise同化这个机制——简单说就是:当你用一个Promise对象去resolve另一个Promise时,规范要求外部Promise必须等内部的Promise完成(状态变成resolved或者rejected),才会继续执行后续的then或者catch回调。

你误以为旧版RSVP.js不支持这个规则,会把p当成普通对象直接返回,但实际上RSVP.js很早就实现了这个行为(除非是非常非常早期的版本)。所以当你调用resolve(p)时,外部Promise并没有立刻完成,而是“挂起”等待p的状态变化,直到5秒后innerResolve()执行,p变成resolved,外部Promise才会触发自己的then回调,输出2。

怎么得到你想要的输出顺序

如果你确实需要让外部Promise立即resolve,把p当作普通值处理,最简单的办法是把p包装成一个非Promise的结构,比如数组或者对象:

new RSVP.Promise(function (resolve) {
  console.log('1');
  var p = new RSVP.Promise(function (innerResolve) {
    setTimeout(function () {
      console.log('3');
      innerResolve();
    }, 5000);
  });
  // 用数组把p包起来,避免被RSVP识别为Promise进行同化
  resolve([p]);
}).then(function (result) {
  console.log('2');
  // 要是之后需要用到p,直接取result[0]就行
});

这样外部Promise会立刻完成,then回调马上执行输出2,5秒后内部Promise的定时器触发,输出3,完全符合你的预期。

当然,如果只是单纯想调整输出顺序,也可以把console.log('2')放到内部Promise的回调里,但估计这不是你想要的实现方式~

最后总结一下

多数旧版本的RSVP.js已经遵循了Promise规范里的同化规则,resolve一个Promise时会自动等待它完成。如果要绕过这个机制,只要把目标Promise包装成普通值(比如数组、对象),不让RSVP识别出来就行。

内容的提问来源于stack exchange,提问作者nogridbag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:12:39