Using Reduce for Synchronizing Async Calls

So let’s say you want to slowly write out a sentence. forEach and map won’t wait for each async call to go through. However, if you form a reduce properly, it has to!

In this example we will be writting text to an empty HTML element.

<div>
  <pre><h1 class="my-text"></h1></pre>
</div>
const myText = document.querySelector('.my-text');

const writeChars = (myText, char) => new Promise((resolve, reject) => {
  return setTimeout(() => {
    myText.innerText += char;
    resolve();
  }, 25);
});

function type(sentence) {
  sentence.split('').reduce((promiseResolver, char) => {
    return promiseResolver.then(() => writeChars(myText, char));
  }, Promise.resolve());
}

type('This is a sentence');
  1. First we grab the h1
  2. Then we write a function that writes to innerText after some time
  3. We wrap the setTimeout in a Promise
  4. We write a function called type
  5. It takes in a string and splits it by char
  6. Each char is then iterated over via the reduce
  7. We return a Promise of writeChars and tell the reduce to resolve said Promise
  8. Each char will wait 25ms to be typed!

Here is a little bit more advanced CodePen:

See the Pen feedread by Regis Boudinot (@selfup) on CodePen.

Conclusion

Nothing crazy, just something we all run into sometimes.

Hope you enjoyed this little micro blog!