【问题标题】:Making a synchronous loop from synchronous callbacks with node.js + Q deferred/promises module使用 node.js + Q deferred/promises 模块从同步回调中​​创建一个同步循环
【发布时间】:2013-02-17 01:02:44
【问题描述】:

流行的 JavaScript 模块 Q 实现了延迟/承诺/期货概念。我认为它主要与 node.js 一起使用,但它也支持浏览器使用。我将它与 node.js 一起使用。

要进行顺序调用,您需要使用 then() 将一个承诺链接到下一个承诺,但在循环中它可能非常违反直觉,我发现很难像这个伪代码那样做:

forever {
    l = getline();

    if (l === undefined) {
        break;
    } else {
        doStuff(l);
    }
}

Q 文档包含一个看起来非常相似的示例:

var funcs = [foo, bar, baz, qux];

var result = Q.resolve(initialVal);
funcs.forEach(function (f) {
    result = result.then(f);
});
return result;

但是在尝试多种方法使这个示例适应我的问题时,我根本没有成功。

与示例代码不同,我不是迭代数组而是希望循环直到满足结束条件。我也总是调用相同的函数。我的函数不会将先前的结果作为下一次调用的参数。每个调用都没有参数,但返回值决定是否继续循环。

这些看似微不足道的差异正在造成某种无法克服的心理障碍。现在我明白为什么很多人无法理解承诺了。

【问题讨论】:

    标签: javascript node.js loops q


    【解决方案1】:

    要记住的关键是,如果您从 then 回调返回一个承诺,那么它将替换现有的承诺。这个想法是,在循环体中执行你想要做的任何事情链的一次迭代之后,你要么返回一个值,这将解决这个承诺,要么你返回一个新的承诺,它将再次执行循环体。

    function iterateUntil(endValue){
      // This line would eventually resolve the promise with something matching
      // the final ending condition.
      return Q.resolve('some value')
        .then(function(value){
          // If the promise was resolved with the loop end condition then you just
          // return the value or something, which will resolve the promise.
          if (value == endValue) return value;
    
          // Otherwise you call 'iterateUntil' again which will replace the current
          // promise with a new one that will do another iteration.
          else return iterateUntil(endValue);
        });
    }
    

    【讨论】:

    • 我确实尝试并未能使递归版本和迭代版本一样工作。我会试试这个,但没有炸毁堆栈的风险吗?我的项目将处理数百万行的文本文件。
    • @hippietrail 这个递归解决方案应该可以工作。这不会杀死堆栈,因为堆栈会为异步操作重新启动,因此then 回调是从下一个进程滴答开始的全新堆栈的开始。
    • 这似乎有效,但我找不到捕获结束条件的方法。我的意思是我希望只有在这个循环完成后才能执行一些代码。事实上,由于if (value == endValue) return value; 行,我很确定它甚至没有结束,因为如果我打印它,我的 endValue 永远不会出现。在不同的地方添加 errbacks 永远不会导致任何被调用。最糟糕的是,Q 似乎抑制了任何堆栈跟踪——当它失败时,它总是默默地失败。
    • 你能把你的尝试添加到问题中吗?仅凭描述很难给出好的建议。
    • 您的回答确实让我更容易处理 Q 的其他一些异步循环问题,所以我接受它。如果我仍然无法破解它,我将更多地解决这个特定问题并发布详细的代码。谢谢。
    【解决方案2】:

    这并不特定于 Q:Synchronous for loop

    【讨论】:

    • 我也使用过这些类型的循环,但是一旦你得到一些嵌套的循环,尤其是不同风格的循环,你最终可能会得到一种新的不可读的意大利面条代码。我经常让自己感到困惑,并决定在这种情况下,没有某种更具可读性的抽象的手工编码是要走的路。尽管我同意你的观点,但对于小脚本中的单个非嵌套循环。
    猜你喜欢
    • 1970-01-01
    • 2015-09-13
    • 2013-09-28
    • 2018-04-18
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 2016-01-24
    • 2023-03-05
    相关资源
    最近更新 更多