【问题标题】:While loop using bluebird promises使用蓝鸟承诺的while循环
【发布时间】:2015-06-05 04:10:18
【问题描述】:

我正在尝试使用 Promise 实现一个 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;
};

这似乎使用了反模式和不推荐使用的方法,如 cast 和 defer。

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

谢谢

【问题讨论】:

  • 你能用文字解释你真正想要完成的事情吗?请记住,忙等待循环在 Javascript 中是一件可怕的事情。使用某种事件处理程序而不是在紧密循环中重复调用某些东西更有意义。而且,action() 是做什么的?或许展示一个你将如何使用它的例子?

标签: javascript promise bluebird


【解决方案1】:

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

【讨论】:

  • 您可以将loop函数更改为接受一个值,然后在谓词为false时解析它,以获取action函数返回的最后一个值。
  • @Sami:是的,例如the answer in the linked question 就是这样做的。但是我想让这个答案接近 OPs 函数,它总是解析为undefined
  • 你能举一个你的promiseWhile的例子吗?这里对如何实际使用它感到非常困惑。
  • 第一个例子中的value是什么?
  • @JakeWilson 这是您要检查的谓词的初始值 当测试函数不带任何参数时,您可以省略它。
【解决方案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;
})

【讨论】:

  • 我可能会使用 Symbol 作为唯一值,但其他方面看起来不错:)
  • 神想本机
猜你喜欢
  • 1970-01-01
  • 2016-08-26
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多