Working with Array#reduce
Asynchronously
While working on a chrome extension that groups tabs together by certain
criterias, I ran across a problem where I was using Array#reduce
and had
to run an asynchronous chrome extension API inside it. In this article, I
will show you how to do asynchronous operations inside Array#reduce
.
What is Array#reduce
?
Array#reduce
allows you to iterate through an array and modify an accumalator
object every iteration, that is provided back to the next element in the next
iteration.
Example with Array#reduce
The following code will run the function every iteration and pass it the current element's value and the current accumalator's value. The default accumalator is set to 0.
How do you use Array#reduce
asynchronously
This diagram might help:
Basically, what happens is that every iteration, you do the asynchronous work,
and return the promise. In the next iteration, the promise is resolved, and then
it is processed as an accumalator. In the end, Array#reduce
will return a promise
which would resolve to the final result. Here is an example:
Over here, we iterate over the array of the first three natural numbers and then
define an asynchronous arrow function that first runs await
on the acc
and
then processes it, returning the new value. The little complicated part is why
we can't just remove line 8 where we await the accumalator.
It might seem like this code will work because we already run await on line 3:
However, Array#reduce
doesn't have any special logic to handle async
functions,
so it just evaluates it like a regular function and sets the value of the accumalator
to the promise returned by the asynchronous function. That means that when our function
recieves its accumalator, it recieves a promise that has to be resolved first.
For example, if we removed the await when assigning newValue
:
To remove the await when assigning newValue
, the next iteration will get a promise
resolving to a promise.