DEV Community

Dealing with Promises In an Array with async/await

Afif Sohaili on June 14, 2019

Promises and async/await is a welcomed addition to the newer versions of JavaScript. If you are not using it yet and are trapped in the callback he...
Collapse
 
inneroot profile image
Gleb

You forget about for await to run async functions one-by-one

async function start() {
  for await (let asyncFunction of asyncFunctions ) {
    console.log(await asyncFunction())
  }
}
start();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
iranrodrigues profile image
iranrodrigues

An added bonus is that you can easily break or return based on the result of each function, if you had to.

Collapse
 
afifsohaili profile image
Afif Sohaili

Updated!

Collapse
 
jzohrab profile image
JZ

Hi Afif, thanks for the post, it was helpful. With help from a user on Reddit, there's another entry you might want to add, "async pools". If it's useful, please copy anything you want from this public gist: gist.github.com/jzohrab/a6701d0087...

Cheers and regards! jz

Collapse
 
afifsohaili profile image
Afif Sohaili

Thanks! That's interesting. Definitely faster than just processing promises one-by-one.

Collapse
 
cortadoj profile image
Cortado-J

Thanks for great post @afif Sohaili.

I'm new to javascript but not new to programming.
I was interested in the "Complete async tasks in sequence" method using reduce as you describe.
In the spirit of "DRY", I immediately wanted to encapsulate it:

    function sequencer(array, waitForThis, andThen){
      return (async function() {
        await array.reduce(async (previousPromise, item) => {
          await previousPromise;
          const result = await waitForThis(item);
          andThen(result)
        }, Promise.resolve());
      })()
    }
Enter fullscreen mode Exit fullscreen mode

which then gives us the re-usable "sequencer" which takes as parameters:

  • An array of values which are passed to each task in the sequence.
  • A function returning a promise to be applied to each of the above.
  • A function to be executed for each result.

which means we can do this:

    const resolveInNSeconds = (n) => {
      return new Promise((resolve) => {
        setTimeout(() => resolve(n), n * 1000);
      })
    };

    const logResult = (result) => {
      console.log(result);
    }

    sequencer([2,3,5], resolveInNSeconds, logResult)
Enter fullscreen mode Exit fullscreen mode

Does this look like sound javascript?

I can't help thinking the resolveInNSeconds function could be a bit simpler?

Collapse
 
afifsohaili profile image
Afif Sohaili

Sorry I hadn't come and check this often enough and missed it. Yes, you can abstract those however you'd like to make it more readable, and functions are something you can toss around in JavaScript.

Collapse
 
4umfreak profile image
Mark Voorberg

Thanks for this. When you write the "explainer" article for number 3, please contrast it with an old-school for loop. I'm interested to see if your opinion changes!

Collapse
 
afifsohaili profile image
Afif Sohaili • Edited

Hi, I just googled for it, and I was mindblown. Definitely will opt for that instead. I didn't know. 😁

This is why I love the comments section!

Edit: I just reread your comment, and 🤔 do you mean the new for await of that came with ES2018?

Collapse
 
4umfreak profile image
Mark Voorberg • Edited

I did not mean for-await-of, I mean:

  for (var i = 0; i < asyncFunctions.length; i++) {
    var result = await asyncFunctions[i]();
    console.log(result);
  }
Enter fullscreen mode Exit fullscreen mode

Less code, less cognitive overhead!

jsfiddle.net/4umfreak/bkqcymuL/

Thread Thread
 
afifsohaili profile image
Afif Sohaili

Yeah, that's definitely a more readable approach. I have to be honest I haven't used for loops in a while so it didn't really occur to me.

Thread Thread
 
afifsohaili profile image
Afif Sohaili

@4umfreak updated the code to use plain ol' for-loops. Took me long enough.

Collapse
 
kor3k profile image
kor3k

there is a nice lib for promises

bluebirdjs.com/docs/api-reference....

Collapse
 
afifsohaili profile image
Afif Sohaili

Yep, definitely a great library for Promises. I just felt like most of the time what I need with Promises are already available in ES6+.

Collapse
 
hgiudatto profile image
Hector

Awesome!! This has helped me a lot refactoring an endpoint in an API that acts as payments cart and was originally implemented using Promise.all. Thank you v.m