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 mostPriority = 0;
  
    // track the no of promises executed
    let taskCompleted = 0;
    
    // return a new promise
    return new Promise((resolve, reject) => {
      
      // run each task in parallel
      promises.forEach(({task, priority}, i) => {
        
        // if the task is done
        // store it in the result
        task.then((value) => {
          result[priority] = value;
          mostPriority = Math.min(mostPriority, i); 
        }).catch((error) => {
          // if the promise is rejected
          // track the rejected promises just for reference
          rejected[priority] = true;
          
          // if the rejected task is the least priority one
          // move to the next least priority
          if(priority === promises[mostPriority].priority){
            mostPriority++;
          }
        }).finally(() => {  
          // if the value priority is not reject
          // and is the least priority
          //resolve with these value
          if(!rejected[priority] && priority === promises[mostPriority].priority){
            console.log(rejected);
            resolve(priority);
          }
          
          // 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() {
  const value = Math.floor(Math.random() * 10);
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(value < 7){
        reject();
      }else{
        resolve(value);
      }
    }, value * 100);
  });
};

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

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

Output:
/*
// rejected promise as per their priority
{
  "1": true,
  "3": true,
  "4": true
}

// resolve promise as per their priority
2
*/

Note:- As the tasks are time bounded, the promise that resolves first, gets printed.