而使用蓝鸟承诺的循环

时间:2015-03-31 17:46:10

标签: javascript promise bluebird

我正在尝试使用promises实现while循环。

此处概述的方法似乎有效。 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;
};

这似乎使用反模式和弃用的方法,如强制转换和延迟。

有没有人知道更好或更现代的方法来实现这一目标?

由于

2 个答案:

答案 0 :(得分:20)

cast可以翻译为resolvedefer应该indeed not be used

您只能通过将then次调用链接并嵌套到初始Promise.resolve(undefined)来创建循环。

function promiseWhile(predicate, action, value) {
    return Promise.resolve(value).then(predicate).then(function(condition) {
        if (condition)
            return promiseWhile(predicate, action, action());
    });
}

此处,predicateaction都可以返回承诺。对于类似的实现,还要查看Correct way to write loops for promise.更接近原始函数

function promiseWhile(predicate, action) {
    function loop() {
        if (!predicate()) return;
        return Promise.resolve(action()).then(loop);
    }
    return Promise.resolve().then(loop);
}

答案 1 :(得分:3)

我更喜欢这种实现,因为它更容易模拟中断并继续使用它:

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