Yet another post about async/await and promises
Tags: javascript, promises, async, await
Published: 2019-01-10 13:31:04

---
title: Yet another post about async/await and promises
published: true
description: How async/await are connected to promises and a real world example!
tags: javascript, promises, async, await
---

This week someone asked for help on Slack while having issues with `async/await` and promises mixed up all together. The guy was using `async/await` and wanted to wait for a bunch of promises to be resolved (in parallel) before moving forward. I suggested him to take a look at `Promise.all` but as soon as he replied I realized he had some misconceptions about the relation between `async/await` and promises.

The intention of this post is to walk step by step on how both things are connected until we finally get into the problem asked on Slack. I assume you understand at least a bit of promises while I show some examples. Let's get started!

<hr>

First basic example of promises usage:
```javascript
function doSomething() {
  return Promise.resolve('#2');
}

const promise = doSomething().then(console.log);

console.log('#1');
```

Things to highlight here:
- `doSomething` function returns a promise (it is resolved already)
- Even though we put the `console.log` with "#2" inside first it gets printed after "#1"

So far so good. It is how promises work so there is nothing special here.

Now let's rewrite it with `async/await` and see how it works:
```javascript
async function doSomething() {
  return '#2';
}

const result = await doSomething();
console.log(result);

console.log('#1');
```

I've just switched to `async/await` and the result is not the same anymore. Now we get "#2" printed before "#1" which is the expected behavior once we're telling our code to wait for `doSomething` before moving forward with its execution.

But how could we get the same behavior with promises? Well, we have to do the same as the code above: wait for `doSomething` and **then** `console.log` in the right order!
```javascript
function doSomething() {
  return Promise.resolve('#2');
}

const promise = doSomething().then(data => {
  console.log(data);

  console.log('#1');
});
```

Cool, but now let's mix things up a bit and see how they behave. What I mean is: half promise, half `async/await`!
```javascript
function doSomething() {
  return Promise.resolve('#2');
}

const result = await doSomething();
console.log(result);

console.log('#1');
```

```javascript
async function doSomething() {
  return '#2';
}

const result = doSomething().then(console.log);

console.log('#1');
```

Well, what do you thing will be printed?

The first one prints "#2" and then "#1". The second one prints "#1" and then "#2".
You will notice that they are the same examples from above and with the same results. But how can we mix `async/await` and promises and keep the "promises" behavior?

Let's take a look at this:
```javascript
function doSomethingPromise() {
  return Promise.resolve('#2');
}

async function doSomethingAsync() {
  return '#2';
}

const somePromise = doSomethingPromise();
const someAsync = doSomethingAsync();

console.log(somePromise); // Promise { ... }
console.log(someAsync); // Promise { ... }
```

When you `console.log` both calls you'll notice that both of them return a promise! That is the connection between `async/await` and promises. When you put `async` in front of a function you're telling that it [will return a promise with the value from the `return` statement resolved](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#Return_value)! When you `await` you're waiting for the promise to be fulfilled, in this case it is the same of calling the `.then` from the returned promise!
*Attention here: We're not handling errors so don't forget you also have `.catch` and `try/catch` to deal with.*

Those were really simple examples! The question asked on Slack had the following code with it:
```javascript
async function myFunction(...params) {
 const value1 = await someFunction1();
 const value2 = await someFunction2(...params);

 // The following code needs to sync
 const whatNow = async () => {
   await value1.forEach(async v1 => {
     someFunction3(v1);
     someFunction4(v1);
     value2.forEach(v2 => {
       someFunction5(v1, v2);
     });
   });
 }

 whatNow();
} 
```

It is a bit more complicated from the previous examples but the problem here is asynchronous code in Javascript as each `someFunctionX` returns a promise. Let's go and see how far we can get from this example.

The first two statements are OK but we can do better. They are OK because they work but we are actually waiting the first promise from `someFunction1` to resolve and then resolving the second one. If we would rewrite it with promises we would have the following:
```javascript
function myFunction(...params) {
  someFunction1().then(value1 => {
    someFunction2(...params).then(value2 => {
      ...
    });
  });
...
}
```

A better strategy is to use [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) which guarantees that both promises will be resolved in parallel before we move forward with our execution. Our code now looks like that:
```javascript
function myFunction(...params) {
  Promise.all([someFunction1(), someFunction2(...params)]).then(([value1, value2]) => {
    ...
  });
  ...
}
```

Cool, it was just a simple rewriting and we're already getting some benefits. But how could we write it with `async/await`? I do prefer `async/await` because it helps a lot the readability of our code, after all we are writing code that other people will have to read and figure out what is does!

As `Promise.all` returns a promise we can easily use the same strategies from the first examples, so:
```javascript
async function myFunction(...params) {
  const [value1, value2] = await Promise.all([someFunction1(), someFunction2(...params)]);
  ...
}
```

Wow! A way better to read now and we are taking the advantage of the parallelism.

Now we have to solve the problem of the `whatNow` function. What he wants is to execute all the promises in parallel as it doesn't make sense to wait for each of them to resolve and then call the next one. Let's go step by step!

The first problem is using `forEach` with `async/await`. `forEach` is a synchronous call which won't help us with asynchronous code (Want to know more? [Read this post here](https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404)). The first thing we have to keep in mind is that we have the `Promise.all` to help us. So we could start like that:
```javascript
async function myFunction(...params) {
  const [value1, value2] = await Promise.all([someFunction1(), someFunction2(...params)]);

  const promises = value1.map(someFunction3); // We have now an array of promises
  
  await Promise.all(promises);
}
```

Things are getting better now. We map over each value of `value1` and return a promise from it, calling `someFunction3`. After that we wait until all those promises are resolved!

But our problem is a bit deeper as we have more than one function to be called for each value of `value1`. Let's see how it would work:
```javascript
async function myFunction(...params) {
  const [value1, value2] = await Promise.all([someFunction1(), someFunction2(...params)]);

  const promises = value1.map(v1 => [someFunction3(v1), someFunction4(v1)]);
  
  await Promise.all(promises);
}
```

Aaand it doesn't work anymore. The reason is that now we are trying to resolve and array within another array of promises inside. Looks like [[Promise, Promise], [Promise, Promise]]. So one strategy is to flatten it! `Array.prototype.flat` is in experimental mode yet so I'm going to use a [polyfill](https://stackoverflow.com/questions/10865025/merge-flatten-an-array-of-arrays-in-javascript). *Array.prototype.flatMap would be a better option but it is also in experimental mode.*
```javascript
async function myFunction(...params) {
  const [value1, value2] = await Promise.all([someFunction1(), someFunction2(...params)]);

  const promises = flatten(value1.map(v1 => [someFunction3(v1), someFunction4(v1)]));
  
  await Promise.all(promises);
}
```

And now we've the desired result! Let's move further!

The next issue is the `forEach` inside the first `forEach`. Let's try to apply the same strategy as before: map over `value2` and return a promise from `someFunction5`.
```javascript
async function myFunction(...params) {
  const [value1, value2] = await Promise.all([someFunction1(), someFunction2(...params)]);

  const promises = flatten(value1.map(v1 => [
    someFunction3(v1),
    someFunction4(v1),
    value2.map(v2 => someFunction5(v1, v2)),
  ]));
  
  await Promise.all(promises);
}
```

Aaaand it works! Wow! It works because we're flattening the array of promises, otherwise it would be creepier than before within an array of arrays of arrays...

Now we can say we are taking full advantage of Javascript asynchronous code because we are not resolving one promise at a time to dispatch the next one, we are dispatching all of them together and waiting for the final result!

# Conclusion

I hope you can now somehow understand how `async/await` is connected to promises: They are basically the same thing but `async/await` provides a syntax easier to read (aaand relies on `try/catch` which is the standard way of handling errors).

The example from above is a real case scenario which was brought from Slack and it has its own peculiarities. Nevertheless it relies deeply in asynchronous code to work in the best way possible which means it can become trickier if you misunderstand some concepts.

If you have any other suggestions for this code just let me know as I know there are different solutions for the same problem! Any tips that might be worth adding just drop in the comments below and I do add it here!

Gist with examples: https://gist.github.com/viniciuskneves/086632be8482e2cd842669d202414249