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

查看:17
本文介绍了当 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?

推荐答案

Promises/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 回调仍然会被调用.但它不会触发 thencatch 回调.就好像那个承诺永远不会达成……永远.

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.

如果您还想停止触发计时器事件,那么这与 Promise 无关,可以使用 clearTimeout 来完成.Bluebird 在 Promise 构造函数中公开了一个 onCancel 回调函数,当一个 Promise 被取消时它会调用这个回调函数.所以你可以用它来删除计时器事件:

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天全站免登陆