So let’s say you have this say(msg) function:

1
2
3
4
5
6
7
8
const say = (msg) => {
return new Promise((res, rej) => {
console.log(msg);
setTimeout(() => {
res();
}, 1000);
});
};

And you want to call it with different parameters in series. What would you do?

Of course, you can always chain up the promises like so:

1
2
3
4
5
say('hello').then(() => {
say('world').then(() => {
say(':)');
});
});

But for more input parameters, this is super tedious and hard to read. So instead, we can use the reduce function creatively to achieve the same goal elegantly:

1
2
3
4
5
['hello', 'world', ':)'].reduce((promise, msg) => {
return promise.then(() => {
return say(msg);
});
}, Promise.resolve());

Note that the last parameter pass to reduce is treated as the initial value for the reduce, so essentially the above code is equal to:

1
Promise.resolve().then(() => say('hello')).then(() => say('world')).then(() => say(':)'));

A even better way would be refactoring the original say(msg) function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const say = (msg) => {
if (typeof msg === 'string') {
return new Promise((res, rej) => {
console.log(msg);
setTimeout(() => {
res();
}, 1000);
});
}
else if (Array.isArray(msg)) {
return msg.reduce((p, m) => {
return p.then(() => say(m));
}, Promise.resolve());
}
};

Then we can use it as:

1
say(['hello', 'world', ':)']);