Execute promises with the Priority

Given a list of promises and their priorities, call them parallelly and resolve with the value of the first promise with the most priority. If all the promises fail then reject with a custom error.

Example

const promises = [
 {status: 'resolve', priority: 4},
 {status: 'reject', priority: 1},
 {status: 'resolve', priority: 2},
 {status: 'reject', priority: 3}
];

resolvePromisesWithPriority(promises);
// {status: 'resolve', priority: 2}

To solve this, in the resolvePromisesWithPriority function we will create a new promise and return it.

Sort the input promises in ascending order of priority and then execute all of these in parallel.

While executing, use a variable to track the most priority promise, if any promise rejects and it is the promise of most priority, update the variable to the next in priority.

In the end, if any promise resolves and it is of most priority, resolve it, else if all the promises fail then reject with the custom error.

To track if all the promises are finished, we will use another variable named taskCompleted.

function resolvePromisesWithPriority(promises) {
  // sort the promises based on priority
  promises.sort((a, b) => a.priority - b.priority);

  // track the rejected promise
  let rejected = {};

  // track the result
  let result = {};

  // track the position of the most priority
  let mostPriorityIndex = 0;

  // track the no of promises executed
  let taskCompleted = 0;

  // return a new promise
  return new Promise((resolve, reject) => {
    // run each promise in parallel
    promises.forEach(({ task, priority }, i) => {
      // if the promise is done
      // store it in the result
      task()
        .then((value) => {
          result[i] = value;
        })
        .catch((error) => {
          // if the promise is rejected
          // track the rejected promises just for reference
          rejected[i] = true;

          // if the rejected promise is the least priority one
          // move to the next least priority
          if (i === mostPriorityIndex) {
            mostPriorityIndex++;
          }
        })
        .finally(() => {
          // if we have least priority promise resolved aka present in the result
          // then resolve with the priority value
          if (!rejected[mostPriorityIndex] && result[mostPriorityIndex]) {
            resolve(promises[mostPriorityIndex].priority);
          } else if (rejected[mostPriorityIndex]) mostPriorityIndex++;

          // track the no of tasks completed
          taskCompleted++;

          // if all the tasks are finished and none of them have been resolved
          // reject with custom error
          if (taskCompleted === promises.length) {
            reject("All Apis Failed");
          }
        });
    });
  });
}
Input:
// create a promise that rejects or resolves
// randomly after some time
function createAsyncTask(val) {
  return function(){
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if(val > 5){
          reject(val);
        }else{
          resolve(val);
        }
      }, val * 1000);
    });
  };
};

const promises = [
  {task: createAsyncTask(6), priority: 1}, 
  {task: createAsyncTask(3), priority: 4}, 
  {task: createAsyncTask(3), priority: 3}, 
  {task: createAsyncTask(5), priority: 2}
];

resolvePromisesWithPriority(promises).then((result)=>{
  console.log(result);
}, (error) => {
  console.log(error);
});

Output:
/*
// resolve promise as per their priority
2
*/

In the above example, task with priority 2 takes 5 seconds to resolve, but because it is a least priority one, we get 2 as output.

Note:- Even though all promises run in parallel, we will only get output when all promises are fulfilled, thus for above example we get output after 6 second which is the max time among all the promises.