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.