Хотя цикл с использованием bluebird promises
Я пытаюсь реализовать цикл while с помощью promises.
Метод, описанный здесь, кажется, работает.
http://blog.victorquinn.com/javascript-promise-while-loop
он использует такую функцию
var Promise = require('bluebird');
var promiseWhile = function(condition, action) {
var resolver = Promise.defer();
var loop = function() {
if (!condition()) return resolver.resolve();
return Promise.cast(action())
.then(loop)
.catch(resolver.reject);
};
process.nextTick(loop);
return resolver.promise;
};
Это похоже на использование анти-шаблонов и устаревших методов, таких как литье и отсрочка.
Кто-нибудь знает лучший или более современный способ добиться этого?
Спасибо
Ответы
Ответ 1
cast
можно перевести на resolve
. defer
должен действительно не использоваться.
Вы создали бы свой цикл только путем цепочки и вложения then
invocations на начальный Promise.resolve(undefined)
.
function promiseWhile(predicate, action, value) {
return Promise.resolve(value).then(predicate).then(function(condition) {
if (condition)
return promiseWhile(predicate, action, action());
});
}
Здесь оба predicate
и action
могут возвращать promises. Для аналогичных реализаций также посмотрите Правильный способ записи циклов для обещания. Ближе к вашей исходной функции будет
function promiseWhile(predicate, action) {
function loop() {
if (!predicate()) return;
return Promise.resolve(action()).then(loop);
}
return Promise.resolve().then(loop);
}
Ответ 2
Я предпочитаю эту реализацию, поскольку ее легче имитировать разрыв и продолжать с ним:
var Continue = {}; // empty object serves as unique value
var again = _ => Continue;
var repeat = fn => Promise.try(fn, again)
.then(val => val === Continue && repeat(fn) || val);
Пример 1: останавливается, когда либо источник, либо конечный пункт указывают на ошибку
repeat(again =>
source.read()
.then(data => destination.write(data))
.then(again)
Пример 2: случайное прекращение, если сбрасывание монеты дает 90% вероятности с 0
var blah = repeat(again =>
Promise.delay(1000)
.then(_ => console.log("Hello"))
.then(_ => flipCoin(0.9) && again() || "blah"));
Пример 3: Петля с условием, которое возвращает сумму:
repeat(again => {
if (sum < 100)
return fetchValue()
.then(val => sum += val)
.then(again));
else return sum;
})