【问题标题】:Recursion with Asynchronous Functions and Bluebird Promises in JavaScript在 JavaScript 中使用异步函数和 Bluebird Promise 进行递归
【发布时间】:2015-02-05 21:27:42
【问题描述】:

在 JavaScript 中,我有四组函数:

Set_A
  synchronousFunction_One
  synchronousFunction_Two
  synchronousFunction_Three
  synchronousFunction_Four
  synchronousFunction_Five

Set_B
   objectA.asynchronousFunction_One
   objectA.asynchronousFunction_Two
                       .
                       .
                       .
   objectA.asynchronousFunction_N

Set_C
   objectA.asynchronousFunction_Three
   objectA.asynchronousFunction_Four
                       .
                       .
                       .
   objectA.asynchronousFunction_M

Set_D
  synchronousFunction_Six

我需要以特定的顺序和特定的约束一个接一个地运行每个集合:

  1. 在解决外部提供的承诺之前,不能调用 Set_A 中的任何函数
  2. Set_A 中的同步函数被迭代,每次调用一次
  3. 每次调用 Set_A 中的函数后,迭代器都会暂停并等待下面的第 4 步和第 5 步解决,然后再移动到 Set_A 中的下一个元素
  4. Set_B 被迭代,每个方法被调用一次,打开几个到互联网的异步连接
  5. 在第 4 步中的所有调用都解决后,将迭代 Set_C 并调用每个方法一次,再次打开几个到 Internet 的异步连接
  6. 一旦第 5 步中的所有调用都已解决,上述第 1 步中的迭代器将移动到 Set_A 中的下一个元素

所以,基本上我们在这里所做的是等待一些外部承诺解决,然后我们调用一个函数来“启动泵”,可以这么说。然后,我们迭代对象接口的一部分,即“独立部分”——可以随时调用的方法。然后,我们迭代该对象接口的另一部分,“依赖部分”(即,除非独立部分中的所有方法都至少关闭一次,否则依赖部分中的任何方法都不会正确关闭)。最后,我们调用清理函数。完成后,我们从 Set_A 中的下一个元素重新开始并再次启动泵。

最高级别的抽象,再次使用 Bluebird Promise 库,如下所示:

function doAllTheThings( externalPromise ) {

  var Set_A, Set_B, Set_C; // Array<Function>

  return new Promise( promiseToDoAllTheThings );
  function promiseToDoAllTheThings( resolve, reject ) {

    externalPromise.then( go );

    function go() {

      var primePump = Set_A.pop();
      if ( !primePump ) return;

      primePump();
      callEverythingInSet_B()
        .then( callEverythingInSet_C )
        .then( cleanUp )
      ;
    }

    function callEverythingInSet_B() {

      var promises = [];
      for ( var index in Set_B )
        promises.push( Set_B[index]() );
      return Promise.all( promises );
    }

    function callEverythingInSet_C() {

      var promises = [];
      for ( var index in Set_C )
        promises.push( Set_C[index]() );
      return Promise.all( promises );
    }

    function cleanUp() {

      // Do stuff
      go();
    }
  }
}

我很难处理这个;昨天我花了几个小时分解和重构,每次都没有得到我预期的行为。我仍在研究我的实际代码;所以也许我会找到让我发疯的奇怪分号或类似的东西。

但与此同时,我想我会在这里发布这个并问 - 我是否正确理解 Bluebird Promise 库?鉴于上面的代码,人们应该期待我所描述的行为吗?如果没有——你能提供一些演示代码吗?

谢谢你。

【问题讨论】:

    标签: javascript recursion iteration promise bluebird


    【解决方案1】:

    是的,这似乎有效。但是,一些提示:

    • 不要将go() 函数的调用放在cleanUp 中。在 go 函数本身的 .then(cleanUp) 之后将其链接起来,使递归性质显而易见(并保持引用本地化)。
    • 那个

      return new Promise( promiseToDoAllTheThings );
      function promiseToDoAllTheThings( resolve, reject ) {
      

      错了。返回的承诺永远不会被解决或拒绝,你不使用那些回调。但是,您甚至根本没有shouldn't use them here。省略promiseToDoAllTheThings,只做一个

       return externalPromise.then( go );
      

      直接。

    • 不要使用那些普通的for 循环,尝试使用Array::map,它看起来会更好:-)
    • 您可以使用 Promise.each 代替 go 循环

    【讨论】:

    • 贝尔吉赢了!谢谢你,兄弟。你连接到蓝鸟?我到处都能看到你,伙计。 (我现在在代码笔中输入所有这些内容;一旦准备好,将为后代提供链接。)
    • 另外——你知道哪个表现更好吗,香草forArray::map?这是服务器端代码,所以我试图坚持快速吸烟。 (因此,蓝鸟的选择。)
    • 不,@BenjaminGruenbaum 和 @Esailija 是蓝鸟作者,我还没有为它做出贡献,但我只是在我自己的(学术)承诺实施方面工作。
    • for-loops are a bit faster as they don't have to call functions。然而,这是一个微优化,目标是干净的代码。网络连接限制了您的方法的性能。
    • 这是@Bergi 建议的主要修订版的 CodePen 模型:http://codepen.io/anon/pen/WbXwVv 效果很好!谢谢,伙计!
    猜你喜欢
    • 1970-01-01
    • 2019-05-16
    • 2015-07-02
    • 2020-02-10
    • 2017-10-24
    • 2014-09-28
    相关资源
    最近更新 更多