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.