Progress of Promises in JavaScript

Progress of Promises in JavaScript

ยท

2 min read

Contents

  1. Overview
  2. Implementation
  3. Conclusion

Overview

Displaying the progress of multiple tasks as they are completed can be helpful to the user as it indicates how long they may need to wait for the remaining tasks to finish.

We can accomplish this by incrementing a counter after each promise has resolved.

The video version of this tutorial can be found here...

Our desired output will look something like this, as the tasks are in progress.

Loading 7 out of 100 tasks

Implementation

Let's start with the markup!

All you need is a script tag to point to a JavaScript file (which will be implemented below), and one div element, whose text will be manipulated to update the progress counter of tasks completed.

<!DOCTYPE html>
<html>
<body>
    <div id="progress"></div>    
    <script src="app.js"></script>
</body>
</html>

Next up, the JavaScript!

We will begin by creating a function which resolves a promise after a random time has passed.

We do this as it closely resembles how it will work in a real-world application, e.g. HTTP requests resolving at different times.

async function task() {
  return new Promise(res => {
    setTimeout(res, Math.random() * 5000);
  })
}

Secondly, we will create an array of 100 promises and update the progress text to inform the user when all of the tasks have finished.

const loadingBar = document.getElementById('loadingBar');

(async() => {
  const promises = new Array(100)
    .fill(0)
    .map(task);

  loadingBar.textContent = `Loading...`;
  await Promise.all(promises);
  loadingBar.textContent = `Loading Finished`;
})();

Now imagine if this takes 30 seconds to complete. All the user will see on screen is the text 'Loading...' whilst it is in progress.

That is not a very useful message!


Let's improve this now by updating the progress text after each task has resolved.

The code snippet below is the full implementation.

const loadingBar = document.getElementById('loadingBar');

async function task() {
  return new Promise(res => {
    setTimeout(res, Math.random() * 5000);
  })
}

function loadingBarStatus(current, max) {
  loadingBar.textContent = `Loading ${current} of ${max}`;
}

(async() => {
  let current = 1;
  const promises = new Array(100)
    .fill(0)
    .map(() => task().then(() => loadingBarStatus(current++, 100)));

  await Promise.all(promises);
  loadingBar.textContent = `Loading Finished`;
})();

Now, you can see that as each promise is resolved, the counter is incremented and displayed to the user.


Conclusion

In short, all you need to do is update the progress as each promise is resolved.

I hope you found this short tutorial helpful.

Let me know your thoughts in the comments below. ๐Ÿ˜Š