当Promise.all()拒绝时,停止其他承诺 [英] Stop other promises when Promise.all() rejects

查看:423
本文介绍了当Promise.all()拒绝时,停止其他承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然关于 Promise.all 的所有问题都集中在如何等待所有承诺,但我想走另一条路 - 当任何承诺失败,停止其他承诺,甚至停止整个脚本。

While all the questions about Promise.all focus on how to wait for all promises, I want to go the other way -- when any of the promises fails, stop the others, or even stop the whole script.

这是一个简短的例子来说明:

Here's a short example to illustrate:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'resolve1');
}).then(a => { console.log('then1'); return a; });

const promise2 = new Promise((resolve, reject) => {
  setTimeout(reject, 2000, 'reject2');
}).then(a => { console.log('then2'); return a; });

const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'resolve3');
}).then(a => { console.log('then3'); return a; });

Promise.all([promise1, promise2, promise3])
  .then(values => { console.log('then', values); })
  .catch(err => { console.log('catch', err); throw err; });

// results:
// > "then1"
// > "catch" "reject2"
// > "then3"    <------- WHY?

脚本继续解析 promise3 ,即使最后的 all(...)。catch()抛出!有人可以解释原因吗?我可以做些什么来阻止他们拒绝的其他承诺?

The script continues to resolve promise3, even though the final all(...).catch() throws! Can someone explain why? What can I do to stop the other promises at the point any of them rejects?

推荐答案

取消承诺不包括在承诺/ A +规范

然而,一些Promise库有这样的取消延期。以 bluebird 为例:

However, some Promise libraries have such a cancellation extension. Take for example bluebird:

Promise.config({ cancellation: true }); // <-- enables this non-standard feature

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'resolve1');
}).then(a => { console.log('then1'); return a; });

const promise2 = new Promise((resolve, reject) => {
    setTimeout(reject, 2000, 'reject2');
}).then(a => { console.log('then2'); return a; });

const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, 'resolve3');
}).then(a => { console.log('then3'); return a; });

const promises = [promise1, promise2, promise3];

Promise.all(promises)
    .then(values => { 
        console.log('then', values); 
    })
    .catch(err => { 
        console.log('catch', err); 
        promises.forEach(p => p.cancel()); // <--- Does not work with standard promises
    });

<script src="https://cdn.jsdelivr.net/bluebird/latest/bluebird.core.min.js"></script>

请注意,即使promise3被取消,其 setTimeout 仍然会调用回调。但它不会触发然后 catch 回调。就好像这个承诺永远不会达成一个决议......永远。

Note that even though promise3 is cancelled, its setTimeout callback will still be called. But it will not trigger the then or catch callbacks. It will be as if that promise never comes to a resolution ... ever.

如果你想也停止触发计时器事件,那么这与承诺无关,可以使用 clearTimeout 完成。 Bluebird在Promise构造函数中公开了 onCancel 回调函数,它将在取消承诺时调用。因此,您可以使用它来删除计时器事件:

If you want to also stop the timer event from triggering, then this is unrelated to promises, and can be done with clearTimeout. Bluebird exposes an onCancel callback function in the Promise constructor, which it will call when a promise is cancelled. So you can use that to remove the timer event:

Promise.config({ cancellation: true }); // <-- enables this non-standard feature

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'resolve1');
}).then(a => { console.log('then1'); return a; });

const promise2 = new Promise((resolve, reject) => {
    setTimeout(reject, 2000, 'reject2');
}).then(a => { console.log('then2'); return a; });

const promise3 = new Promise((resolve, reject, onCancel) => { // Third argument (non-standard)
    var timer = setTimeout(resolve, 3000, 'resolve3');
    onCancel(_ => {
        clearTimeout(timer);
        console.log('cancelled 3');
    });
}).then(a => { console.log('then3'); return a; });

const promises = [promise1, promise2, promise3];

Promise.all(promises)
    .then(values => { 
        console.log('then', values); 
    })
    .catch(err => { 
        console.log('catch', err); 
        promises.forEach(p => p.cancel()); // <--- Does not work with standard promises
    });

<script src="https://cdn.jsdelivr.net/bluebird/latest/bluebird.core.min.js"></script>

这篇关于当Promise.all()拒绝时,停止其他承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆