最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - break promise.all on catch - Stack Overflow

programmeradmin2浏览0评论

I have a promise implementation like the one on MDN:

    var p1 = new Promise((resolve, reject) => {
        setTimeout(resolve, 1000, "one");
    });
    var p2 = new Promise((resolve, reject) => {
        setTimeout(resolve, 2000, "two");
    });
    var p3 = new Promise((resolve, reject) => {
        setTimeout(resolve, 3000, "three");
    });
    var p4 = new Promise((resolve, reject) => {
        setTimeout(resolve, 4000, "four");
    });
    var p5 = new Promise((resolve, reject) => {
        reject("reject");
    });
    
    Promise.all([p1, p2, p3, p4, p5]).then(value => {
        console.log(value);
    }, function(reason) {
        console.log(reason)
    });

I have a promise implementation like the one on MDN:

    var p1 = new Promise((resolve, reject) => {
        setTimeout(resolve, 1000, "one");
    });
    var p2 = new Promise((resolve, reject) => {
        setTimeout(resolve, 2000, "two");
    });
    var p3 = new Promise((resolve, reject) => {
        setTimeout(resolve, 3000, "three");
    });
    var p4 = new Promise((resolve, reject) => {
        setTimeout(resolve, 4000, "four");
    });
    var p5 = new Promise((resolve, reject) => {
        reject("reject");
    });
    
    Promise.all([p1, p2, p3, p4, p5]).then(value => {
        console.log(value);
    }, function(reason) {
        console.log(reason)
    });

This does fast error-catching:

Promise.all is rejected if one of the elements is rejected and Promise.all fails fast: If you have four promises which resolve after a timeout, and one calls reject immediately, then Promise.all rejects immediately.

However, the functions inside a promise don't stop running. What I want, is that if one function does a reject, the other functions stop running (preventing useless messages to a user).

Example of a promise that keeps running after the reject:

var p1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, "one");
});
var p2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, "two");
});
var p3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, "three");
});
var p4 = new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log('Don\'t show this after a reject!');
        resolve();
    }, 4000);
});
var p5 = new Promise((resolve, reject) => {
    reject("reject");
});

Promise.all([p1, p2, p3, p4, p5]).then(value => {
    console.log(value);
}, function(reason) {
    console.log(reason)
});

Share Improve this question asked Jul 2, 2016 at 9:36 RandyRandy 9,8495 gold badges42 silver badges58 bronze badges 2
  • 1 Keep in mind that many async operations involve networking and once they are started, some agent on some other server is already busy doing what you asked it to do. You can abort parsing the response when that es back (or kill the network connection so not response will be received), but you often cannot tell the agent on some other server to actually stop doing what it's doing. Very few networking operations have that capability. – jfriend00 Commented Jul 2, 2016 at 15:48
  • Also, another possibility is to put your processing for all the results in the Promise.all().then(...) handler. Then you will not show the user anything unless all things succeeded because you will know at that time whether there was an error or not. – jfriend00 Commented Jul 2, 2016 at 15:51
Add a ment  | 

1 Answer 1

Reset to default 4

There's nothing general in promises that will do that, since stopping the other actions is action-specific, not generic. For instance, in your example, you have to keep the timer handle and then use clearTimeout; with an ajax request, you might need to do an abort call; with something else, it would be something else.

So you'll need to handle this in your real code in a way that's specific to your real code, using .catch on the promise returned by Promise.all (or the second arg to then as you have).

In the specific code in your question, it would look something like this (I've added output to the timers we don't cancel as well), but again it will vary depending on what you're cancelling:

var timersToReject = [];
var p1 = new Promise((resolve, reject) => {
    setTimeout(v => {
        console.log("resolving " + v);
        resolve(v);
    }, 1000, "one");
});
var p2 = new Promise((resolve, reject) => {
    setTimeout(v => {
        console.log("resolving " + v);
        resolve(v);
    }, 2000, "two");
});
var p3 = new Promise((resolve, reject) => {
    setTimeout(v => {
        console.log("resolving " + v);
        resolve(v);
    }, 3000, "three");
});
var p4 = new Promise((resolve, reject) => {
    timersToReject.push(setTimeout(() => {
        console.log('Don\'t show this after a reject!');
        resolve();
    }, 4000));
});
var p5 = new Promise((resolve, reject) => {
    reject("reject");
});

Promise.all([p1, p2, p3, p4, p5]).then(value => {
    console.log(value);
}, function(reason) {
    console.log(reason)
    timersToReject.forEach(t => clearTimeout(t));
});

发布评论

评论列表(0)

  1. 暂无评论