Я пытаюсь понять отказоустойчивое поведение Promises.all. Рассмотрим приведенный ниже пример;
let p1 = new Promise(function(resolve, reject) {
setTimeout(
function(){
console.info("p1");
resolve('p1');
}, 500);
});
let p2 = new Promise(function(resolve, reject) {
setTimeout(
function(){
console.info("p2");
resolve('p2');
}, 1000);
});
let p3 = new Promise(function(resolve, reject) {
setTimeout(
function(){
console.info("p3");
resolve('p3');
}, 1200);
});
let p4 = new Promise(function(resolve, reject) {
setTimeout(
function(){
console.info("p4");
reject('p4');
}, 600);
});
let p5 = new Promise(function(resolve, reject) {
setTimeout(
function(){
console.info("p5");
resolve('p5');
}, 800);
});
let promise = Promise.all([p1, p2, p3, p4, p5]);
promise
.then(function(data) {
data.forEach(function(data) {
cconsole.info(data);
});
})
.catch(function(error) {
console.error('error is', error);
});
Запуск приведенного выше примера делает журнал п1, п2, п3, п4, п5 а затем журналы "ошибка p4"
Вот что я прочитал о Promise.all;
Promise.all has a fail-fast behaviour. If a given promise is rejected, the resulting promise of Promise.all will be rejected at this exact moment. It will not wait for the other promises to complete
Итак, мой вопрос: почему/как он регистрирует p1, p2, p3, p4, p5
Я думал, что он должен был просто зарегистрировать p1 (поскольку это меньше 600 мс, при котором у нас есть отклонение), а затем просто записать «ошибка p4»
Где мое понимание может быть неправильным?
Я немного обновил пример... Все еще вижу тот же результат
Ваше обновление существенно меняет вопрос, но по-прежнему имеет место то, что вызовы console.info() происходят независимо от работы механизма Promise. Тайм-ауты не отменяются, когда один из обратных вызовов терпит неудачу.
Если одно отклоненное обещание отменит все другие обещания, другие обещания будут отменены в недетерминированной точке, и это было бы очень плохо, возьмем, например, Promise.all([ notifyUser(), storeToDB() ]), если уведомление пользователя не удалось, и это отменит операцию базы данных, вы можете повредить база данных. Вместо того, чтобы активно отменять эти другие действия, вы должны разделить эти действия на несколько многообещающих функций, которые вы затем вызываете по частям, например. Promise.all([notifyUser(), prepareDB()]).then(() => Promise.all([storeDB(), sthElse()]));



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я думаю, что отказоустойчивое поведение лучше проиллюстрировать на примере
function logFulfilled(val) {
console.info(val + " fulfilled");
return val;
}
function timeout(callback, delay, val) {
console.info(val + " created");
setTimeout(callback, delay, val);
}
let p1 = new Promise(function(resolve, reject) {
timeout(resolve, 500, 'p1');
}).then(logFulfilled);
let p2 = new Promise(function(resolve, reject) {
timeout(resolve, 1000, 'p2');
}).then(logFulfilled);
let p3 = new Promise(function(resolve, reject) {
timeout(resolve, 1200, 'p3');
}).then(logFulfilled);
let p4 = new Promise(function(resolve, reject) {
timeout(reject, 600, 'p4');
}).catch(err => {
console.info(err + " rejected");
throw err;
});
let p5 = new Promise(function(resolve, reject) {
timeout(resolve, 800, 'p5');
}).then(logFulfilled);
let promise = Promise.all([p1, p2, p3, p4, p5]);
promise.then(console.info, console.error);Обратите внимание, что вы получаете журнал Error сразу после отклонения p4, до того, как будут выполнены p5, p2 и p3.
Спасибо. Но он продолжает регистрировать выполнение p5, p2, p3 даже после отклонения p4.
@testndtv Да, потому что обещания не могут остановить основное действие — setTimeout продолжает выполняться, оно не отменяется. Дело в том, что promise сразу же отвергается, вот и все, что означает «Promise.all быстро выходит из строя».
@testndtv fail-fast означает, что обещание, возвращенное Promise.all, будет отклонено, как только будет отклонено одно из промисов прохождения, не дожидаясь завершения остальных. Это не значит, что остальные промисы прерываются, они все равно закончат свое действие.
Вызовы
console.info()происходят сразу, а не после тайм-аутов.