Reputation: 647
I have a function called _problemFunction
which takes an array myList as argument. For every item in myList I call a function _myFunction
. _myFunction
returns a promise. I want to return resolve from _problemFunction if _myFunction
returns resolve with any item of my list. I want to return reject from _problemFunction
if _myFunction
returns reject for all the items in myList. Below is the code block of the scenario:
_problemFunction = (myList) => {
return new promise((resolve, reject) => {
myList.forEach(listItem => {
_myFunction(listItem).then(pass => {
//Resolve when _myFunction returns resolve with any listitem argument
}).catch(fail => {
//reject only if _myfunction returns rejects for all the listitems
})
})
})
}
Upvotes: 0
Views: 82
Reputation: 493
As i understood, you want to reject only if all the promises reject, so you have to know if the rejects are the same amount of the array length to run the reject callback, something like this:
return new promise((resolve, reject) => {
let rejectCount = 0
let resolved = false
for(let listItem of myList){
_myFunction(listItem).then(pass => {
//Resolve when _myFunction returns resolve with any listitem argument
if(!resolved){
resolved = true
resolve(pass)
}
}).catch(fail => {
//reject only if _myfunction returns rejects for all the listitems
rejectCount++
if(rejectCount === myList.length) {
reject(fail)
}
})
if(resolved) break
}
})
If you have edge cases where your list is empty or undefined you can add this check before the for loop:
if(!myList || myList.length === 0) {
reject(new Error('list is empty or undefined')
return
}
Upvotes: 1
Reputation: 39250
It depends if you want to do all the items in the list in parallel or in series:
To resolve on the very first item that resolves and reject with all errors in series:
//serial resolve on first resolved item
_problemFunction = (myList,failed=[]) => {
if(myList.length===0){
return Promise.reject(failed);
}
return _myFunction(myList[0])
.catch(
//try it again with the next item
err=>_problemFunction(myList.slice(1),failed.concat([err]))
)
}
Try all at once and return whatever resolves first but reject with all the failed ones (unless your list is empty then it'll fail with an empty list)
//parallel resolve on first resolved item reject when all reject
_problemFunction = (myList,failed=[]) => {
if(failed.length===0){
myList = myList
.map(([item,index])=>
[
index,
_myFunction(item)
.catch(err=>Promise.reject([err,index]))
]
);
}
if(myList.length===0){
return Promise.reject(failed);
}
return Promise.race(
myList.map(([i,p])=>p)
)
.catch(
([err,index])=>//an error remove the failed item and try again
_problemFunction(
myList.filter(([i,p])=>i!==index),
failed.concat([err])
)
)
}
Upvotes: 0
Reputation: 1430
Take a look at Promise.all() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
let request = data.map((i) => {
return new Promise((resolve, reject) => {
if(i < 1) {
reject('value to low')
}
resolve(i);
}); });
return Promise.all(data) });
Upvotes: 1
Reputation: 388
_problemFunction = (myList) => {
return new promise((resolve, reject) => {
const errs = [];
myList.forEach(listItem => {
_myFunction(listItem)
.then(resolve)
.catch(fail => {
errs.push(fail);
errs.length === myList.length ? reject(errs) : '';
})
})
})
}
Upvotes: 1