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!