简体   繁体   中英

While loop using bluebird promises

I am trying to implement a while loop using promises.

The method outlined here seems to work. http://blog.victorquinn.com/javascript-promise-while-loop it uses a function like this

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;
};

This seems to use anti-patterns and deprecated methods like cast and defer.

Does anyone know a better or more modern way to accomplish this?

Thanks

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;
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM