Отказоустойчивое поведение Promises.all

Я пытаюсь понять отказоустойчивое поведение 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() происходят сразу, а не после тайм-аутов.

Pointy 23.02.2019 15:20

Я немного обновил пример... Все еще вижу тот же результат

copenndthagen 23.02.2019 15:31

Ваше обновление существенно меняет вопрос, но по-прежнему имеет место то, что вызовы console.info() происходят независимо от работы механизма Promise. Тайм-ауты не отменяются, когда один из обратных вызовов терпит неудачу.

Pointy 23.02.2019 15:33

Если одно отклоненное обещание отменит все другие обещания, другие обещания будут отменены в недетерминированной точке, и это было бы очень плохо, возьмем, например, Promise.all([ notifyUser(), storeToDB() ]), если уведомление пользователя не удалось, и это отменит операцию базы данных, вы можете повредить база данных. Вместо того, чтобы активно отменять эти другие действия, вы должны разделить эти действия на несколько многообещающих функций, которые вы затем вызываете по частям, например. Promise.all([notifyUser(), prepareDB()]).then(() => Promise.all([storeDB(), sthElse()]));

Jonas Wilms 23.02.2019 15:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
4
356
1

Ответы 1

Я думаю, что отказоустойчивое поведение лучше проиллюстрировать на примере

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.

copenndthagen 23.02.2019 15:35

@testndtv Да, потому что обещания не могут остановить основное действие — setTimeout продолжает выполняться, оно не отменяется. Дело в том, что promise сразу же отвергается, вот и все, что означает «Promise.all быстро выходит из строя».

Bergi 23.02.2019 15:36

@testndtv fail-fast означает, что обещание, возвращенное Promise.all, будет отклонено, как только будет отклонено одно из промисов прохождения, не дожидаясь завершения остальных. Это не значит, что остальные промисы прерываются, они все равно закончат свое действие.

t.niese 23.02.2019 15:37

Другие вопросы по теме