While loop using bluebird promises
cast
can be translated to resolve
. defer
should indeed not be used.
You'd create your loop only by chaining and nesting then
invocations onto an initial Promise.resolve(undefined)
.
function promiseWhile(predicate, action, value) {
return Promise.resolve(value).then(predicate).then(function(condition) {
if (condition)
return promiseWhile(predicate, action, action());
});
}
Here, both predicate
and action
may return promises. For similar implementations also have a look at Correct way to write loops for promise. Closer to your original function would be
function promiseWhile(predicate, action) {
function loop() {
if (!predicate()) return;
return Promise.resolve(action()).then(loop);
}
return Promise.resolve().then(loop);
}
I prefer this implementation as its easier to simulate break and continue with it:
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);
Example 1: stops when either the source or the destination indicate an error
repeat(again =>
source.read()
.then(data => destination.write(data))
.then(again)
Example 2: stop randomly if the coin flip given 90% probability results with a 0
var blah = repeat(again =>
Promise.delay(1000)
.then(_ => console.log("Hello"))
.then(_ => flipCoin(0.9) && again() || "blah"));
Example 3: Loop with condition that returns the sum:
repeat(again => {
if (sum < 100)
return fetchValue()
.then(val => sum += val)
.then(again));
else return sum;
})