Вы действительно близки со своим редуктором!
Начальное значение для редуктора: Promise.resolve()
, поэтому при первом вызове функции:
chain.reduce(function(promise, item) {
// ^^ promise is a resolved promise,
// ^^ item is chain[0]
return promise.then(function() {
console.log("then:", item);
// ^^ when the promise resolves (immediately) this is called
// BUT no value is returned.
}), Promise.resolve();
});
Сравните это с ручной цепочкой обещаний. Вы бы вернули следующее обещание ждать:
Promise.resolve()
.then(item => { console.log("then: ", item); return fn("10"); })
.then(item => { console.log("then: ", item); return fn("20"); })
.then(item => { console.log("then: ", item); return fn("30"); })
Видите, как редуктор так близко? Мы просто хотим вернуть обещание:
var chain = [fn("10"), fn("20"), fn("30")];
chain.reduce(function(promise, item) {
return promise.then(function() {
console.log("then:", item);
return item;
}), Promise.resolve();
});
Редактировать :
Если вызов fn
начинает работу, каждое из этих назначений запускает вызовы не по порядку:
chain.length = 0;
chain[2] = fn("30");
chain[1] = fn("20");
chain[0] = fn("10");
Чтобы запустить каждый fn
в нужном вам порядке, вам придется отложить вызов до fn
до разрешения предыдущего вызова. Мы сделали это в нашем примере выше. В зависимости от сложности ваших данных, вы можете уменьшить массив аргументов для fn
или заключить каждый вызов в функцию, которая не будет выполняться:
[10,20,30]
.reduce(function(promise, arg) {
return promise.then(function() {
return fn(arg);
}), Promise.resolve();
});
[function() { return fn(10); }, function() { return fn(20) }, function() { return fn(30) }]
.reduce(function(promise, callFn) {
return promise.then(function() {
return fn(callFn);
}), Promise.resolve();
});