【问题标题】:Dealing with rejected promises without messy try catch处理被拒绝的承诺,而不用混乱的 try catch
【发布时间】:2020-06-01 14:48:55
【问题描述】:

我有一个简单的函数,看起来类似于下面的

const foo = (bar) => {

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

}

apiRequest 返回一个数字。

这个函数被一个处理许多函数错误的函数包围。

但是对于这个特定的功能,我不只是想在三元组的第二部分中的一个 apiRequests 失败的情况下向用户返回错误。

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
}

我不完全确定我应该怎么做。也许我可以用 try 和 catch 包围每个部分,然后在 catch 语句中我可以尝试逻辑的下一部分?

我觉得在这种情况下我最终会得到一个超级混乱的功能

【问题讨论】:

  • 如果两个 apiRequest 都失败了怎么办?
  • 你不能在非异步函数中使用await
  • 我怀疑你正在寻找一个简单的apiRequest.catch(err => 0)

标签: javascript node.js promise async-await


【解决方案1】:

首先,await 需要出现在 async 函数中,因此您问题中的代码无法运行。

如果我理解正确,你仍然希望函数在 both 都被拒绝时返回被拒绝的承诺。

您可以定义一个实用函数,它将数组作为 Promise 并返回一个仅在 all 给定 Promise 拒绝时才拒绝的 Promise(原因是第一个 Promise 被拒绝)。在所有其他情况下,它将解析为具有单个已实现值的数组,或者在相应的 Promise 被拒绝时使用默认值。

这个实用函数可能如下所示:

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);
}

那么你的函数可能如下所示:

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

【讨论】:

  • 你知道,有Promise.any :-)
  • 是的,我不是这个意思。我改了名字。
【解决方案2】:

你可以试试这个

  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
    }

@trincol 回答,如果两个承诺之一失败,它会将提醒添加到默认值,如果所有承诺都失败,它将抛出错误并且不会返回值,它不会返回默认值. 所以我调整了这样的代码

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)
   )
}

【讨论】:

    猜你喜欢
    • 2021-08-02
    • 2018-07-04
    • 1970-01-01
    • 2017-12-07
    • 2018-07-09
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多