Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async-Await: How to get data in multiple await calls even when there is an error in one?

So I have this async function where I make multiple calls to NodeJS's DNS Api. The first two calls return data but because of the third one, the catch block triggers and I don't get the data from the first two.

As it all depends on the type of query(netflix.com), some of the await operations might throw an error because of no data. But what I want is I want to get data from the other calls even if there are errors from some of them.

Here's the code:

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

The above code returns

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

Individual outputs from the first two queries:

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' }
]

How I want to display the data:

[
  { 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 }
]

Please note that there will be around 6 calls to the DNS API. It cannot be determined which one will trigger an error because of no data. It totally depends on the query.

like image 606
s.khan Avatar asked Jan 24 '21 18:01

s.khan


People also ask

What happens if await throws error?

If a promise resolves normally, then await promise returns the result. But in the case of a rejection, it throws the error, just as if there were a throw statement at that line. In real situations, the promise may take some time before it rejects. In that case there will be a delay before await throws an error.

How do I handle multiple async-await?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

How do you catch error in async function?

Using catch() on the Function Call Remember that async functions always return promises. This promise rejects if any uncaught error occurs in the function. If your async function body returns a promise that rejects, the returned promise will reject too.


1 Answers

This is the very use case Promise.allSettled is for:

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

Or if you only want the successful results:

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`...
like image 122
T.J. Crowder Avatar answered Sep 28 '22 04:09

T.J. Crowder