简体   繁体   English

JavaScript中具有异步功能和Bluebird承诺的递归

[英]Recursion with Asynchronous Functions and Bluebird Promises in JavaScript

In JavaScript, I have four sets of functions: 在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

I need each set to be run one after another, in a particular order and with certain constraints: 我需要每个集合以特定的顺序并受一定的约束依次运行:

  1. None of the functions in Set_A can be called until an externally provided promise resolves 在外部提供的promise解析之前,不能调用Set_A中的任何函数
  2. The synchronous functions in Set_A are iterated over, called once each Set_A中的同步函数被迭代,每次调用一次
  3. After each call to a function in Set_A, the iterator pauses and waits for Step 4 and Step 5, below, to resolve before moving onto the next element in Set_A 每次调用Set_A中的函数后,迭代器会暂停并等待下面的第4步和第5步解析,然后再移至Set_A中的下一个元素
  4. Set_B is iterated over and each method is called once, opening several asynchronous connections to the internet Set_B被迭代,并且每个方法都被调用一次,从而打开了几个与Internet的异步连接
  5. Once all of the calls in Step 4 have resolved, Set_C is iterated over and each method is called once, again opening several asynchronous connections to the internet 解决了第4步中的所有调用后,将遍历Set_C并调用每个方法一次,从而再次打开与Internet的多个异步连接
  6. Once all calls in Step 5 have resolved, the iterator in Step 1, above, moves on to the next element in Set_A 解决完第5步中的所有调用后,上述第1步中的迭代器将移至Set_A中的下一个元素

So, essentially what we are doing here is waiting for some external promise to resolve, then we call a function to "prime the pump", so to speak. 因此,实际上,我们在这里所做的就是等待一些外部承诺得到解决,然后我们可以说是一个函数“启动泵”。 Then, we iterate over part of an object's interface, the "independent part"--methods that can be called whenever one likes. 然后,我们遍历对象接口的一部分,即“独立部分”,即只要有人喜欢就可以调用的方法。 Then, we iterate over another part of that object's interface, "the dependent part" ( ie none of the methods in the dependent part will close properly unless all of the methods in the independent part have closed at least once ). 然后,我们迭代该对象接口的另一部分“从属部分”(即,除非独立部分中的所有方法至少关闭了一次,否则从属部分中的所有方法都无法正确关闭)。 And then finally, we call the cleanup function. 最后,我们调用清理函数。 Once that is done, we start over with the next element in Set_A and prime the pump again. 完成此操作后,我们从Set_A中的下一个元素开始,然后再次灌注泵。

The highest level of abstraction, again using the Bluebird Promise Library, looks like this: 再次使用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();
    }
  }
}

I'm having a really hard time with this; 我在这方面很难过。 I spent several hours yesterday factoring and refactoring, every time not getting the behavior I expected. 昨天我花了几个小时进行分解和重构,每次都没有达到我预期的行为。 I'm still working on my actual code; 我仍在编写我的实际代码; so maybe I'll find the odd semicolon that's driving me crazy or something like that. 所以也许我会发现令我发疯的奇怪的分号或类似的东西。

But in the meantime, I thought I'd post this here and ask--am I understanding the Bluebird Promise Library correctly? 但是与此同时,我想我应该在这里发帖问我-我是否正确理解Bluebird Promise库? Given the code above, should one expect the behavior I've described? 给定上面的代码,应该期待我描述的行为吗? If not--can you provide some demo code that will? 如果没有,您能否提供一些演示代码?

My follicles thank you. 我的卵泡谢谢你。

Yes, that seems to work. 是的,这似乎可行。 However, some tips: 但是,一些技巧:

  • don't put your call of the go() function in cleanUp . 不要将对go()函数的调用放在cleanUp Chain it right after the .then(cleanUp) in your go function itself, making the recursive nature obvious (and keeping the references local). go函数本身中的.then(cleanUp)之后.then(cleanUp)它,从而使递归性质显而易见(并使引用保持局部)。
  • That

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

    is wrong. 是错的。 The returned promise is never resolved or rejected, you don't use those callbacks. 返回的承诺不会被解决或拒绝,您不会使用这些回调。 However, you even shouldn't use them here at all. 但是,您甚至根本不应该在这里使用它们 Just omit that promiseToDoAllTheThings , and only do a 只是忽略了promiseToDoAllTheThings ,只做一个

      return externalPromise.then( go ); 

    directly. 直。

  • Instead of those plain for loops, try to use Array::map , it'll look better :-) 代替普通的for循环,尝试使用Array::map ,它看起来会更好:-)
  • you may use Promise.each instead of your go loop 您可以使用Promise.each而不是go循环

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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