Promise.all API 调用,区分哪个抛出错误,只拒绝一个
Posted
技术标签:
【中文标题】Promise.all API 调用,区分哪个抛出错误,只拒绝一个【英文标题】:Promise.all API calls, distinguish which threw error and reject only one 【发布时间】:2020-11-07 17:55:40 【问题描述】:所需信息:使用 NodeJS 框架,Promises.all 仅与 API 调用一起使用,因此异步代码
所以我的问题的基础在于我需要创建两个 API 调用,我们称它们为 A 和 B。保证 A 将返回数据或 404,而 B 将返回空数组、数据或404(但这里的 404 表示无效输入,而在 API 调用 A 中,它实际上表示未找到资源)。我的问题是,如果 A 确实返回 404,Promise.all 将像往常一样拒绝并跳入 catch 块。
我想要的功能是,如果 API 调用 A 返回 404,我希望 API 调用 B 继续并检索该数据,继续我的代码。有没有办法区分甚至分别捕获两个 API 调用引发的错误,如果一个解决了则继续执行??
示例代码目前如下所示:
function(param)
const A = apiCallA();
const B = apiCallB();
return Promise.all([A, B])
.then( ([resA, resB]) =>
// If resA is null, catch the error but continue with
// resB. If this is null also Promise.reject('both API calls failed')
// else if both resA && resB != null, do some stuff and resolve
)
.catch( (err) =>
// Here is where my question lies. The err object can be either from API call A or B.
// How would I distinguish this?
);
【问题讨论】:
【参考方案1】:有多种选择。
您可以在 Promise.all()
之前从 API 调用 A 中捕获错误,并将其转换为成功的请求,但已适当标记,从而允许 Promise.all()
完成。
无论成功或失败,您都可以使用Promise.allSettled()
获得这两个结果。
对于第一个选项,您可以在 apiCallA()
上放置一个 .catch()
处理程序,它将任何拒绝转换为解决,但会使用错误对象进行解决,您可以稍后检查是否需要:
function(param)
const A = apiCallA().catch(err => return err );
const B = apiCallB();
return Promise.all([A, B]).then( ([resA, resB]) =>
// you can check if resA succeeded here
if (resA instanceof Error)
// resA actually failed
console.log(resA);
).catch( (err) =>
// you would only get here if resB failed
);
对于第二个选项,您使用Promise.allSettled()
:
function(param)
const A = apiCallA();
const B = apiCallB();
return Promise.allSettled([A, B]).then( ([resA, resB]) =>
// check both resA.status and resB.status
if (resA.status === "fulfilled")
console.log(resA.value);
if (res === "fulfilled")
console.log(resB.value);
);
【讨论】:
第二个选项Promise.allSettled()
听起来非常完美。你能再描述一下吗? MDN 文档 (developer.mozilla.org/en-US/docs/Web/javascript/Reference/…) 给我留下了一些问题。我会留意文字“履行”和“拒绝”吗?我还能添加一个 catch 块吗?编辑:我现在看到你已经更新了答案。我会试试这个,从编程和逻辑上看,看起来正是我需要的。
@MariosYiannakou - 我添加了Promise.allSettled()
的代码示例
@MariosYiannakou - 如果这回答了您的问题,您可以通过单击答案左侧的复选标记向社区表明这一点。这也将为您在此处遵循正确的程序赢得一些声誉积分。
您的第一个解决方案效果更好,因为 Promise.allSettled 未被识别为函数。不确定我是否遗漏了一些东西。只是想让其他阅读本文的人知道。
@MariosYiannakou - 你运行的是什么版本的 nodejs?我认为Promise.allSettled()
是在节点 v12.9.0 中添加的。以上是关于Promise.all API 调用,区分哪个抛出错误,只拒绝一个的主要内容,如果未能解决你的问题,请参考以下文章
在 node js 中使用 promise.all 进行外部 api 调用
为啥即使我 .catch() Promise.all() 也会抛出异常?
如何使用并区分Promise.all和Promise.race?
节点使用带有 .catch() 语句的 Promise.all 为 Mongoose 请求抛出 UnhandledPromiseRejectionWarning