Functional JavaScript: Resolving Promises Sequentially
Tags: javascript, functional
Published: 2017-11-01 18:00:54

---
title: "Functional JavaScript: Resolving Promises Sequentially"
published: true
description: 
tags: javascript, functional
cover_image: https://thepracticaldev.s3.amazonaws.com/i/wr97cdb2oivfbaf2pxvu.jpg
---

I love the new [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) library that ships with ES6, though one thing has been left out, a function to sequentially execute multiple promises.

We can use a library like [Q](https://github.com/kriskowal/q), [Bluebird](https://github.com/petkaantonov/bluebird), [RSVP.js](https://github.com/tildeio/rsvp.js/), [Async](https://github.com/caolan/async), etc., or we can make our own. I really only need a single function and it seemed kind of heavy to import a whole library for one function which is why I created this.

One trait of the Promise is that it executes immediately. This actually works against us, we’ll need the Promises to execute when we are ready for it to execute.

The way I did this was to convert each Promise into a factory function. The factory function will be a simple function that will return a Promise. Now our Promises will execute when _we_ decide.

For this \*cough\* contrived example, I’ve decided to use jQuery’s ajax method as my promise.

```javascript
// some dummy urls to resolve
const urls = ['/url1', '/url2', '/url3']

// convert each url to a function that returns an ajax call
const funcs = urls.map(url => () => $.ajax(url))
```

Solving this problem is a little complex, and I find it helps me to think ahead a little bit about what our function should output. Probably something like this:


```javascript
Promise.resolve()
  .then(x => funcs[0]()) // resolve func[0]
  .then(x => funcs[1]()) // resolve func[1]
  .then(x => funcs[2]()) // resolve func[2]
```

I also want the final promise to return an array that contains the results of each promise.

This was the most complex part. I needed to start each promise with an empty array `[]` and then concatenate the results of each promise to that array. Stick with me, I’ll try my best to break it down.

I’m gonna start off this Promise with an initial value of an empty array like this `Promise.resolve([])`. Then execute each factory function using the Promise’s `then` function.

For simplicity sake, this example just resolve index `0` of func. We’ll do the rest later.

```javascript
// start our promise off with an empty array. this becomes all.
Promise.resolve([])
  // all is the array we will append each result to.
  .then(all => {
    return funcs[0]().then(result => {
      // concat the resolved promise result to all
      return all.concat(result)
    })
   })
```

This block of code can be expressed this in a more compact way by removing all the `{`, `}`, and `return` from our code.


```javascript
Promise.resolve([])
  .then(all => funcs[0]().then(result => all.concat(result)))
```

A neat trick to get rid of that arrow function is directly call `concat` like this:

```javascript
Promise.resolve([])
  .then(all => funcs[0]().then(Array.prototype.concat.bind(all)))
```

And finally, this will be the output of our function:

```javascript
Promise.resolve([])
  .then(x => funcs[0]().then(Array.prototype.concat.bind(x)))
  .then(x => funcs[1]().then(Array.prototype.concat.bind(x)))
  .then(x => funcs[2]().then(Array.prototype.concat.bind(x)))
```

That wasn’t so bad was it? Now that we know our input and output, let’s make!

We could use a for loop (but that’s not very functional), we could also use recursion, but what I really like for this problem is `reduce`.

> Whenever you need to transform a list into a single object, consider using reduce.

Our `promiseSerial` function should take an array of factory functions (that each return a Promise) and reduce them into the single Promise chain expressed above.

Our initial value of `Promise.resolve([])` is passed into our reduce method like this:

```javascript
const promiseSerial = funcs =>
  funcs.reduce((promise, func) => ???, Promise.resolve([]))
```

The last piece is to generalize one of our Promise `then`'s from above and update some argument names. (the new part is in bold)

```javascript
const promiseSerial = funcs =>
  funcs.reduce((promise, func) =>
    promise.then(result =>
      func().then(Array.prototype.concat.bind(result))),
      Promise.resolve([]))
```

That’s it! A pretty simple... scratch that... short function that will resolve Promises sequentially.
Lastly, let’s slap it all together.

```javascript
/*
 * promiseSerial resolves Promises sequentially.
 * @example
 * const urls = ['/url1', '/url2', '/url3']
 * const funcs = urls.map(url => () => $.ajax(url))
 *
 * promiseSerial(funcs)
 *   .then(console.log)
 *   .catch(console.error)
 */
const promiseSerial = funcs =>
  funcs.reduce((promise, func) =>
    promise.then(result => func().then(Array.prototype.concat.bind(result))),
    Promise.resolve([]))

// some url's to resolve
const urls = ['/url1', '/url2', '/url3']

// convert each url to a function that returns a promise
const funcs = urls.map(url => () => $.ajax(url))

// execute Promises in serial
promiseSerial(funcs)
  .then(console.log.bind(console))
  .catch(console.error.bind(console))
```

Now we have eliminated the need to install a 3rd party library with our shiny new `promiseSerial` function.

Hey! You actually made it to the end of this article!

What is your use case for resolving promises sequentially? How did you solve this? Please share your experiences.

I know it’s a small thing, but it makes my day when I get those follow notifications here and Twitter ([@joelnet](https://twitter.com/joelnet)). Or if you think I’m full of shit, tell me in the comments below.

Cheers!

More Articles @ https://medium.com/@joelthoms/latest

Originally posted @ https://hackernoon.com/functional-javascript-resolving-promises-sequentially-7aac18c4431e