Async-Await:即使一个错误,如何在多个等待调用中获取数据?

Posted

技术标签:

【中文标题】Async-Await:即使一个错误,如何在多个等待调用中获取数据?【英文标题】:Async-Await: How to get data in multiple await calls even when there is an error in one? 【发布时间】:2021-04-28 15:14:44 【问题描述】:

所以我有这个async 函数,我在其中多次调用NodeJS 的DNS Api。前两个调用返回数据,但由于第三个调用,catch 块触发,我没有从前两个调用中获取数据。

由于这完全取决于查询的类型(netflix.com),一些等待操作可能会因为没有数据而引发错误。但我想要的是我想从其他调用中获取数据,即使其中一些调用存在错误。

代码如下:

const dnsResolve = async () => 
    const query                 = 'netflix.com';

    try
        const aRecord           = await dns.resolve4(query);
        const aaaaRecord        = await dns.resolve6(query);
        const cnameRecord       = await dns.resolveCname(query);
     
        console.log(aRecord);
        console.log(aaaaRecord);
        console.log(cnameRecord);
    catch(err) 
        console.log(err);
    


dnsResolve();

以上代码返回

Error: queryCname ENODATA netflix.com
    at QueryReqWrap.onresolve [as oncomplete] (internal/dns/promises.js:167:17) 
  errno: undefined,
  code: 'ENODATA',
  syscall: 'queryCname',
  hostname: 'netflix.com'

前两个查询的单独输出:

aRecord: [
   address: '51.73.1.12' ,
   address: '55.83.62.128' ,
   address: '12.12.82.118' 
]
aaaaRecord:  [
   address: '2406:da200:ff00::222c0:598a' ,
   address: '24206:da00:ff00::22c2:44203' ,
   address: '2406:da0e0:ff00::36de2:41fd' 
]

我想如何显示数据:

[
   address: '51.73.1.12' ,
   address: '55.83.62.128' ,
   address: '12.12.82.118' ,
   address: '2406:da200:ff00::222c0:598a' ,
   address: '24206:da00:ff00::22c2:44203' ,
   address: '2406:da0e0:ff00::36de2:41fd' ,
   NO CNAME RECORDS 
]

请注意,DNS API 将收到大约 6 个电话。由于没有数据,无法确定哪个会触发错误。这完全取决于查询。

【问题讨论】:

【参考方案1】:

这正是Promise.allSettled 的用例:

const results = await Promise.allSettled([
    dns.resolve4(query),
    dns.resolve6(query),
    dns.resolveCname(query),
]);
for (const status, value, reason of results) 
    if (status === "fulfilled") 
        // Promise was fulfilled, use `value`...
     else 
        // Promise was rejected, see `reason` for why...
    

或者如果你只想要成功的结果:

const results = await Promise.allSettled([
    dns.resolve4(query),
    dns.resolve6(query),
    dns.resolveCname(query),
]);
const values = results.filter((status) => status === "fulfilled")
                      .map((value) => value);
// ...use `values`...

【讨论】:

嘿伙计。所以我应该完全删除 try-catch 块? @A.Amit - allSettled 提供的承诺保证永远不会被拒绝。 抱歉这个菜鸟问题。所以从这个意义上说,我可以删除 try-catch 块? @A.Amit - 不用担心!您可以删除try/catch,如果其中唯一的awaitawait来自allSettled 的承诺,是的,因为它永远不会被拒绝并且allSettled 处理任何拒绝承诺你会进入它。如果你有 other 可能会被拒绝的承诺并且你想处理它们,那么你会保留它,但如果你将所有承诺传递给allSettled,则不需要它并使用它的结果。

以上是关于Async-Await:即使一个错误,如何在多个等待调用中获取数据?的主要内容,如果未能解决你的问题,请参考以下文章

在 Vuejs 中使用 async-await 等待函数内部的赋值

捕获 async-await 快速路由处理程序中的所有错误

如何使用async-await然后在一个Mocha测试中完成?

如何在for-each循环中使用async-await? [重复]

在 .net 4 上使用 async-await

Python-即使出现一些错误,如何继续我的测试脚本