Implementing Sequential Execution of Asynchronous Tasks in JavaScript
Problem Statement
Given n asynchronous tasks, these n asynchronous tasks must be executed sequentially, and each subsequent asynchronous task depends on the result of the previous one as its parameter. How do we implement this?
Solution 1: for loop + await
A simple for loop iterates sequentially, unlike Array.forEach and Array.map, which execute concurrently. Leveraging this characteristic along with async / await, it is easy to write code like the following:
1 | (async () => { |
Output:
1 | now is 0 |
Although this achieves the desired effect, the param local variable is rather unpleasant to look at. See Solution 2.
Solution 2: Array.prototype.reduce
When most people first encounter the Array.prototype.reduce method, they use it to sum an array. If you are not familiar with it, you can click the link to learn about reduce.
reduce has the concepts of an initial value, an accumulator, and a current value. The accumulator can be thought of as the previous value, and by returning the accumulator it can also be thought of as the next value (this may sound convoluted; you can refer to the source code of Redux’s middleware execution order, which also uses reduce). The code that uses reduce to solve the problem is:
1 | const sleep = delay => { |
Output:
1 | now is 0 |
You can understand prev and task as follows:
- prev: the previous asynchronous task (promise)
- task: the current asynchronous task
The current asynchronous task needs the result of the previous asynchronous task as its parameter, so it obviously needs to await prev.