0

I have a simple function, which looks similar to the following

const foo = (bar) => {

return ![val1, val2].includes(bar) ? await apiRequest :
await apiRequest + await apiRequest2

}

apiRequest returns a number.

This function is surrounded by a function which handles errors for many functions.

However for this specific function, I don't just want to return an error to the user in the case of one of the apiRequests failing in the second part of the ternary.

const foo = (bar) => {

return ![val1, val2].includes(bar) ? await apiRequest :
await apiRequest + await apiRequest2

// intended logic for second part of ternary
if apiRequest and apiRequest resolve, return apiRequest + apiRequest2
if apiRequest fails, return apiRequest2
if apiRequest 2 fails, return apiRequest
}

I'm not exactly sure of the way I should be going about this. Perhaps I could surround each part with try and catch, and in the catch statement I could then try the next part of the logic?

I feel like I will end up with a super messy function in this case

Ben Williams
  • 91
  • 1
  • 1
  • 5

2 Answers2

1

First of all, await needs to occur in an async function, so the code in your question cannot run.

If I understand correctly, you still want the function to return a rejected promise when both promises reject.

You could define a utility function that takes an array as promises and returns a single promise that only rejects when all given promises reject (with the reason of the rejection of the first promise). In all other cases it will resolve to an array with the individual fulfilled values, or with the default value when the corresponding promise rejected.

This utility function could look like this:

async function fulfilled(promises, defValue) {
    const res = await Promise.allSettled(promises);
    if (res.every(p => p.status == "rejected")) throw res[0].reason;
    return res.map(p => p.status == "fulfilled" ? p.value : defValue);
}

Then your function could look like this:

const foo = async (bar) => {
    return ![val1, val2].includes(bar) ? apiRequest :
        (await fulfilled([apiRequest, apiRequest2], 0)).reduce((a, b) => a + b);
}

trincot
  • 317,000
  • 35
  • 244
  • 286
-1

You can try this

  defaultval="no value"
    const foo = async (bar,apiCalls,defaultval) => {
        var finalresult= await Promise.allSettled(apiCalls)
    .then(resp=>resp.map(p=>p.status==='fulfilled'?p.value:defaultval))
    .then((res)=>{
        var finalnumber=res.filter(x=>x!='no value')
        return finalnumber.length==0?defaultval:finalnumber.reduce((a, b) => a + b)
    })
        return  ![val1, val2].includes(bar) ? apiRequest : finalresult
    }

as answered by @trincol if one of the two promises fail it will add the reminder to the default value, if all promises fail it will throw an error and won't return a value, it won't return a default value. So I adjusted the code like this

defaultval="no value"

async function fulfilled(apiCalls,defaultval) {
    const res = await Promise.allSettled(apiCalls);
    return res.map(p => p.status == "fulfilled" ? p.value:defaultval)
}

const foo = async (bar,defaultval) => {
   var result= await fulfilled([apiRequest, apiRequest2])
   var numb=result.filter(x=>x!=defaultval)
   return ![val1, val2].includes(bar) ? apiRequest :(numb.length==0?defaultval:numb.reduce((a, b) => a + b)
   )
}
Sven.hig
  • 4,449
  • 2
  • 8
  • 18