【问题标题】:Events and Callbacks, need to wait before two events triggered and call callback事件和回调,需要等待两个事件触发并调用回调
【发布时间】:2015-10-29 10:03:04
【问题描述】:

代码可以简化成这样,

function start(callback) {
    one.on('ready', () => {
        console.log('one server ready');
    });

    two.on('ready', () => {
        console.log('two connection ready');
    });

    one.connect();
    two.start();
}

在两个服务都进入就绪状态后,我需要调用 callback。最好的模式是什么?

更新:欢迎提出如何使用 RxJS 做到这一点的想法 :)

【问题讨论】:

  • 你应该使用.once()而不是.on()
  • 异步并行是另一种情况。然后我有一堆异步函数,需要执行并触发单个回调。这里我没有函数,我有事件发射器。
  • 只需将它们包装到异步函数中并在事件处理程序中调用它们的回调

标签: javascript node.js promise rxjs async.js


【解决方案1】:

jQuery ($):

$('#greet').one('click', function(evt){
  $(evt.currentTarget).one('click', function(){
    alert('Hi!');
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button id="greet">Greet ONLY on second click.</button>

祝你好运……

【讨论】:

    【解决方案2】:

    您可以查看event-as-promise 包。它不断地将事件转换为 Promise,直到您完成所有事件处理。

    在你的情况下,

    import EventAsPromise from 'event-as-promise';
    
    const oneReady = new EventAsPromise();
    const twoReady = new EventAsPromise();
    
    one.once('ready', oneReady.eventListener);
    two.once('ready', twoReady.eventListener);
    
    await Promise.all([one.upcoming(), two.upcoming()]);
    

    在这种情况下比 RxJS 更简单、更干净。

    【讨论】:

      【解决方案3】:

      接近它的 RxJS 方法是使用 zipwhen/and/thenDo 进行同步,并使用 fromEvent 管理 EventEmitter

      function ready(ee) {
        return Rx.Observable.fromEvent(ee, 'ready');
      }
      
      //EITHER
      var option1 = Rx.Observable.when(ready(one).and(ready(two))
                                       .thenDo((first, second) => "Both Ready!"));
      
      //OR
      var option2 = Rx.Observable.zip(ready(one), ready(two), 
                                      (first, second) => "Both Ready!");
      
      option1.take(1).subscribe(() => callback());
      

      【讨论】:

        【解决方案4】:

        技术含量低

        一个低技术的方法是维护一个事件计数器,然后当你收到足够的时候调用回调:

        function start (callback) {
        
            var numSteps = 2;
            var currStep = 0;
        
            var step = function () {
        
                currStep++;
                if (currStep === numSteps) {
                    callback();
                }
            }
        
            one.once('ready', () => {
        
                step();
                console.log('one server ready');
            });
        
            two.once('ready', () => {
        
                step();
                console.log('two connection ready');
            });
        
            one.connect();
            two.start();
        }
        

        【讨论】:

        • 谢谢,我知道那种模式……但对我来说它看起来太笨拙了。寻找更多有趣的想法。
        • 这种模式被称为“异步信号量”或只是一个信号量。
        【解决方案5】:

        您要求承诺,让我们看看我们如何将一次性事件转换为承诺,也就是 promisifying 发射器:

        function ready(ee){
            return new Promise(function(resolve) {
                ee.on("ready", resolve); // resolve when ready
            });
        }
        

        这会让你做什么:

        Promise.all([ready(one), ready(two)]).then(function(){
           // both ready here
        });
        

        您可以轻松地聚​​合承诺,这非常好:)

        【讨论】:

        • 好一个。事业的承诺在这里真的很明显..看到一些替代方案会很有趣..)
        • @alexanderb 的替代品很好。请记住,承诺是标准和前进的方向。期待越来越多的 API 迁移到它们。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-19
        • 2018-03-17
        • 2012-04-20
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 1970-01-01
        相关资源
        最近更新 更多