【问题标题】:How to early exit a composition of Promises [duplicate]如何提前退出 Promise 的组合[重复]
【发布时间】:2017-01-04 14:06:13
【问题描述】:

我想做这样的事情:

return1stPromise()
  .then(if1stPromiseSucceeds) // returns 2nd Promise
  .catch(if1stPromiseFails)
  .then(if2ndPromiseSucceeds) // execute only if 1st Promise succeeds

我希望第二个 .then 仅在第一个 Promise 成功时执行。或者换一种说法——如果 catch 已经执行,我不希望第二个 .then 执行。

这是否可能,或者我是否将第二个承诺嵌套在第一个 then 中,如下所示:

return1stPromise()
  .then(function (data) {
    return if1stPromiseSucceeds(data).then(if2ndPromiseSucceeds);
  })
  .catch(if1stPromiseFails);

此外 - 关于如何使用 Promises 控制流的任何好的资源,它更像线程?

【问题讨论】:

  • 如果链中的任何承诺失败,您的catch 将被调用,而不仅仅是第一个。您能更具体地说明您希望发生的事情吗?
  • “这可能吗”。是的。您发布的内容将按此方式工作。
  • 对不起,我不够清楚:我希望第二个 .then 仅在第一个 Promise 成功时执行。或者换一种说法——如果catch 已经执行,我不希望第二个.then 执行。更新的问题。
  • @krulik:嗯,这大大改变了问题。
  • 我相信你真正想要的是return1stPromise().then(x => if1stPromiseSucceeds(x).then(if2ndPromiseSucceeds), if1stPromiseFails)。看看here 的区别。

标签: javascript promise


【解决方案1】:

您所描述的通常是我们想要对异常做出反应但不实际处理它并让代码继续运行的情况:

return1stPromise()
  .then(if1stPromiseSucceeds) // returns 2nd Promise
  .catch(() => { if1stPromiseFails(); throw e; })
  .then(if2ndPromiseSucceeds) // execute only if 1st Promise succeeds

您需要重新抛出异常以将其标记为“仍未处理”。

这就像同步代码:

try {
  var res = firstResult();
  var res2 = ifFirstPromiseSucceeds(res);
} catch (e) {
    ifFirstPromiseFails();
    throw e; // we reacted to the exception but did not handle it yet.
}
var res3 = ifSecondPromiseSucceeds();

我认为从线程的角度考虑 Promise 大多是令人困惑的 - 如果可能的话,找到一个 同步 类比总是更容易。

这并不总是可能的,例如另一种阻止承诺链的方法是 cancellation 这有点像线程中止,具有“我不关心结果”语义 -你可以read about it here 但我认为对于你的用例来说它有点过头了,而且不是很好。

【讨论】:

  • 有道理,谢谢!
  • 唯一的问题是,在我的具体情况下,我宁愿不抛出另一个错误(捕获没有意义)。
  • 同时采用嵌套替代方案(使用嵌套代码更新答案)。
【解决方案2】:

我可能会做投掷和接球,但如果你不想这样做,你总是可以返回一个被拒绝的承诺来绕过下一个 then 阶段。比如;

new Promise((resolve,reject) => { var rnd = Math.random();
	                              rnd > 0.5 ? resolve(21)
	                                        : reject("promise error");
                                })
    .then(val  => { var rnd = Math.random();
                    if (rnd < 0.5) return Promise.reject("then error");
                    return Promise.resolve(val*2);
                  })
    .catch(err => { console.log(err);
                    return Promise.reject("you won't see this");
                  })
    .then(val  => console.log("Both the promise and the first then stage worked fine and resulted: ", val));

只有在第一个 then 阶段的第一个承诺和第二个承诺解决时,才会调用最后一个 then 阶段回调。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 2016-05-07
    • 2019-07-04
    • 2015-12-27
    • 2017-08-28
    • 2021-01-11
    • 2014-05-01
    相关资源
    最近更新 更多