admin管理员组

文章数量:1289620

The code could be simplified to something like that,

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

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

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

I need to call that callback, after both services getting to ready state. What's the best pattern for that?

Update: Ideas how to do that with RxJS are wele :)

The code could be simplified to something like that,

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

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

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

I need to call that callback, after both services getting to ready state. What's the best pattern for that?

Update: Ideas how to do that with RxJS are wele :)

Share Improve this question edited Aug 6, 2015 at 10:11 Alexander Beletsky asked Aug 6, 2015 at 9:57 Alexander BeletskyAlexander Beletsky 19.8k10 gold badges64 silver badges86 bronze badges 4
  • You should probably use .once() rather than .on(). – Matt Harrison Commented Aug 6, 2015 at 10:00
  • 2 github./caolan/async#parallel – deyhle Commented Aug 6, 2015 at 10:02
  • async parallel is for another case.. then I'm having a bunch of async functions, that need to be executed and single callback triggered. Here I don't have function, I have eventemitters. – Alexander Beletsky Commented Aug 6, 2015 at 10:05
  • 1 Just wrap them into async functions and call their callback in the event handler – deyhle Commented Aug 6, 2015 at 10:08
Add a ment  | 

5 Answers 5

Reset to default 8

You asked for promises, let's see how we can convert one time events to promises, aka promisifying the emitters:

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

Which would let you do:

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

You can easily aggregate promises which is very nice :)

The RxJS way of approaching it would be to use either zip or when/and/thenDo for the synchronization, and fromEvent to manage the 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());

Low-tech

A low-tech way is to maintain a counter of events and then call the callback when you have received enough:

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

You can look at the event-as-promise package. It convert events into Promise continuously until you are done with all the event processing.

In your case,

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.uping(), two.uping()]);

Simple and cleaner than RxJS in this case.

With jQuery ($):

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

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

Good Luck...

本文标签: