17

As i understand it, Promise.all() executes everything in parallel and returns a error at the first instance of error in either of the Promises.

Now what if i want to run all promises in parallel and wait for them to complete even if one of them were to fail ?

Is there a Promise method or module i'm supposed to use ?

Im sending a bunch of users FCM push notifications in parallel and Failing the .then() queueing if any one of them fails is not intended.

I'm Doing this in my code

//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;
    })
};
AL.
  • 36,815
  • 10
  • 142
  • 281
Sanket Berde
  • 6,555
  • 4
  • 35
  • 39

1 Answers1

39

You could do something like this:

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

This will resolve all the Promise objects with errors to a null in the resulting array. You could also keep the Error object using .catch(error => error), to detect failures at the end, or resolve to an object with { status, result, error } properties.

salezica
  • 74,081
  • 25
  • 105
  • 166
  • Thanks, this looks great ! – Sanket Berde Apr 19 '17 at 19:04
  • is it optimal good practice to use `Promise.all( )`, what about performance – Ashish Kamble Jul 10 '19 at 05:22
  • 1
    This is just as performant as using `Promise.all` with no wrapper at all. Your promises are probably asynchronous, so CPU power should not be an issue. Memory-wise, unless you have an array of 100.000 promises, don't worry. – salezica Jul 11 '19 at 22:04
  • If you didn't see the notice at the top with the other stack overflow about Promise.allSettled go check it out. – user1819575 Sep 15 '21 at 21:35
  • Feel free to have a look at Promise.allSettled() > The Promise.allSettled() method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled – hpl002 Jan 26 '22 at 12:39