Handling async operations and promise values in javascript arrays
Tags: javascript, es6
Published: 2019-10-22 19:08:12

---
title: Handling async operations and promise values in javascript arrays
published: true
description: Applying async operations to javascript array items
tags: javascript, ES6
cover_image: https://thepracticaldev.s3.amazonaws.com/i/8t7qsu137df38h94v522.jpg
---

ES6 brought a lot of notable goodies to javascript and one of the famous ones are [async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) and popular array methods like [map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map), [filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) and [foreach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/foreach). These operations all take a callback and have their various ideal use cases but whichever one you use, try not to sacrifice code legibility.

To the main reason we are here, I have often had difficulties in the past using these array methods whenever my callback had to be an async function or handle a Promise. I eventually got to figure it out and put this piece together in case anyone else faces these struggles. I will give examples using the map and reduce methods. The knowledge from both can be applied to the other methods which are quite similar.

## MAP

I use the map operation when I need to return an identical array but with each value going through the same modification. Let's assume we have a function 'findById' that takes a data's id and returns the corresponding data to that id. If we have an array of ids and we want to get the corresponding data for each of these ids, we could easily do

```javascript
const getData = (arrayOfIds) => {
 const arrayOfData = arrayOfIds.map(id => findById(id));
 console.log(arrayOfData);
}

```

`arrayOfData` should contain our data right? Well, that depends. If findById is a synchronous function, then yes. If it an async function, what we get in our console is an empty array. Why? javascript [event loop](https://nodejs.org/de/docs/guides/event-loop-timers-and-nexttick) drama. The thread won't wait for the completion of the findById operations before moving to the next operation.

Now let us treat `findById` as an async function and fix our code to ensure our promise is resolved before running any operations that depend on our resolved data.

```javascript
 const getData = (arrayOfIds) => {
  Promise.all(arrayOfIds.map(id => findById(id)))
   .then((arrayOfData) => {
     console.log(arrayOfData);

     //do what you want with data
  });
 }

```
We should now see our data instead of an empty array in the console. [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) is used to resolve an array of Promises. `findById` will return a Promise, so our map operation will return an array of Promises, hence the need for `Promise.all`. This solution, however, can be even neater if getData is an async function, so we can resolve our promise with a simple `await`

```javascript
 const getData = async (arrayOfIds) => {
  const arrayOfData = await Promise.all(
    arrayOfIds.map(id => findById(id))
  );

  console.log(arrayOfData);

  // do what you want with data
 }

```
Easy peasy!

## Reduce

I use `reduce` when I want to fluently aggregate my array into a single value. For our reduce example, we will be trying to convert an array of ids into a javascript Object. Let us will assume our `findById` method returns object data that contains a name field, so we want to convert our array of ids to an object with each data's id as a key and the name as corresponding value. Something that looks like this

```javascript
 {
  53b55aea-32f8-47fe-aa36-9fd44f6c399f: 'Alec Benjamin',
  53b55aea-32f8-47ff-aa37-9fdhjdj5678f: 'Chester Bennington'
 }
```

Here is how we can implement this

```javascript
const getUserDataInDictFormat = async (arrayOfIds) => {
  const userData = await arrayOfIds.reduce(async (prevAggregate, currentId) => {
    const currentUserData = await findById(currentId);
    
    const aggregate = await prevAggregate;

    aggregate[currentId] = currentUserData.name;

    return aggregate;
  }, {})
 }

 console.log(userData);

 //do something with userData
}
```

Since our callback returns a Promise on each iteration, our prevAggregate will need to be awaited to get its value. The final value of the reduce operation will also be a Promise,  which we also await to get its resolved value.

The secret for me is, try as much as possible to figure out which values will be a promise and ensure they are resolved before using them again. 
I hope this was helpful and feel free to drop a comment if you have any concerns.