xyzims
xyzims

Reputation: 135

async.js with async / await - need help explaining why this doesn't work

I am currently using async.js v2.3.0 with ES2017 async support.

I'm trying to figure out why the function doSomething which returns a promise works in the IIEF but doSomething2 isn't respected. Is it because doSoomething2 is an async function but isn't exactly running "async" code? I feel like I'm missing something here.

function promiseTimeOut() {
 return new Promise((resolve, reject) => {
   setTimeout(() => {
     resolve(20);
   }, 1000);
 })
}

function doSomething() {
 return new Promise((resolve, reject) => {
   async.retry({
     times: 5,
     interval:(retryCount)=>{ return 50 * Math.pow(2, retryCount); }
   }, async () => {
     return await promiseTimeOut();
   }, (err, result) => {
     resolve(result);
   });
 })
}

async function doSomething2() {
 async.retry({
   times: 5,
   interval:(retryCount)=>{ return 50 * Math.pow(2, retryCount); }
 }, async () => {
   return await promiseTimeOut();
 }, (err, result) => {
   return result;
 });
}

// main function
(async () => {
 async.series([
   (callback) => {
     callback(null, 1);
   }, 
   async () => {
     return await doSomething();
   },
   async () => {
     // doesn't get waited on, returns undefined right away
     return await doSomething2();
   }
 ], (err, result) => {
   // result: 1, 20, undefined
   console.log(result);
 });
})()

Upvotes: 1

Views: 222

Answers (2)

nicolas-van
nicolas-van

Reputation: 1051

Async.js is performing decompilation on your code to adapt its behavior depending if you are using async function (that return promises) or callback-based functions. That's why you can see a different behavior, it simply depends on the simple fact of having an "async" keyword or not in front of your function (even if the behavior should be the same).

Frankly that's not a very good idea. Async.js is not bad at what is does but is clearly a library that was built to ease the use of callbacks and that was later upgraded to try to work with promises. Unfortunately that kind of auto-magic behavior based on decompilation can and will cause problems. As example it can make the code behave completely differently depending on if you're using a precompiler like Babel or not.

I recently published a library which is an alternative to async.js and that was precisely made to use only Promises (and async/await), thus making a fully-consistant library to work using those newer tools.

The result is named modern-async and is here: https://nicolas-van.github.io/modern-async/

Upvotes: 0

hgb123
hgb123

Reputation: 14891

You are writing async.retry in callback style, so that it won't wait until it finished. Try to console.log(result), you could see

[ 1, 20, undefined ]
20

Look at the doc for retry, as well as other method, it cited that

Returns: a promise if no callback provided

So you just have to immediately return without provide any callback

async function doSomething2() {
  return async.retry(
    {
      times: 5,
      interval: (retryCount) => {
        return 50 * Math.pow(2, retryCount)
      },
    },
    async () => {
      return await promiseTimeOut()
    }
  )
}

Upvotes: 1

Related Questions