One of the problems at the end of the chapter on asynchronous programming in Modern JavaScript for the Impatient is to:
Write a loop that invokes the produceRandomAfterDelay function from the preceding exercises n times and prints the sum once the summands are available.
This was an interesting problem that helped me understand JavaScript promises much better. The most important learning is that promises are deferred operations and the only way to get results out of a promise is to use then
. From the docs:
Promise.resolve().then(() => console.log(2));
console.log(1);
// Logs: 1, 2
Promises are how the simpler async
and await
declarations are implemented, understanding the basics about promises is important. Anyway, my implementation of the above problem was the following:
const invokeAfterDelay = (fn, delay) => {
return new Promise((resolve, reject) => {
const callback = () => resolve(fn());
setTimeout(callback, delay);
});
}
const sumRandomLoop = (n) => {
let p = Promise.resolve();
let sum = 0;
for (let i = 1 ; i <= n; i++) {
p = p.then(() => invokeAfterDelay(Math.random, 1000)
.then((data) => {
sum += data;
if (i === n) console.log(sum);
}));
}
};
sumRandomLoop(10);
It took a couple of tries to get it into my head that the only way to get something out of a promise is to use then
. I’m not sure if this is the most effective way to solve the problem, but it works and I can generalize from it.