Promise.all() Альтернатива, допускающая отказ?

Насколько я понимаю, Promise.all() выполняет все параллельно и возвращает ошибку при первом появлении ошибки в любом из промисов.

А что, если я хочу запустить все промисы параллельно и дождаться их завершения, даже если одно из них не сработает?

Есть ли метод или модуль Promise, который я должен использовать?

Я отправляю группе пользователей push-уведомления FCM параллельно, и сбой очереди .then(), если какой-либо из них не работает, не предназначен.

Я делаю это в своем коде

//then chain

    .then(()=>{
            let startChatPromises = [];
            for (let i = 0 ; i < queue_length ; i ++){
                startChatPromises.push(matchUsers(some_key,some_key));
            }
            return Promise.all(startChatPromises);
        }).then(()=>{// Continue processing even after failure ?});


let matchUsers = (room_id,...user_ids) => {

    let chat_key = admin.database().ref().child("chats").child(room_id).push().key;

    let participants = {};

    user_ids.forEach(user_id=> {
        participants[`${user_id}`] = true;
    });

    return admin.database().ref().child("chats").child(room_id).child(chat_key).update({
        "last_message_ts" : new Date().getTime(),
        "participants" : participants
    }).then(()=>{
        //Get Users
        let getFCMTokenPromises = [];
        user_ids.forEach(user_id => {
            getFCMTokenPromises.push(admin.database().ref("users").child(user_id).child("fcm_id").once('value'));
        });
        return Promise.all(getFCMTokenPromises);
    }).then(results => {
        // Send Push Notifications
        let tokens = [];
        results.forEach(snapshot=>{
            if (snapshot.val() !== undefined && snapshot.val() !== null && snapshot.val() !== "")
                tokens.push(snapshot.val());
        });
        const payload = {
            data: {
                NOTIFICATION_TYPE: 'START_CHAT',
                CHAT_UID: chat_key
            }
        };
        return admin.messaging().sendToDevice(tokens, payload);
    }).catch(()=>{
        return true;
    })
};

person Sanket Berde    schedule 19.04.2017    source источник


Ответы (1)


Вы можете сделать что-то вроде этого:

function allSkippingErrors(promises) {
  return Promise.all(
    promises.map(p => p.catch(error => null))
  )
}

Это разрешит все объекты Promise с ошибками в null в результирующем массиве. Вы также можете сохранить объект Error, используя .catch(error => error), для обнаружения сбоев в конце или разрешить объект со свойствами { status, result, error }.

person slezica    schedule 19.04.2017
comment
Спасибо, это выглядит великолепно! - person Sanket Berde; 19.04.2017
comment
оптимально ли использовать Promise.all( ), как насчет производительности - person Ashish Kamble; 10.07.2019
comment
Это так же эффективно, как использование Promise.all вообще без оболочки. Ваши обещания, вероятно, асинхронны, поэтому мощность процессора не должна быть проблемой. С точки зрения памяти, если у вас нет массива из 100 000 промисов, не беспокойтесь. - person slezica; 12.07.2019