1

If I have an object thats fetching data and it emits a "ready" event but another object starts listening for that event after it has already been fired is there a direct way of allowing that listener to receive that missed event.

Purely hypothetical example (so please don't ask why I would do this):

function DataModule(){
    this.data = null;
    request.get( 'http://example.com/api/get/data', function( error, response, body ) {
        if ( ! err ) {
            this.data = body;
            this.emit( 'ready' );
        }
    }.bind( this ) );
}

...

var dataModule = new DataModule(); // data fetching happens here.
setTimeout( function(){
    dataModule.once( 'ready', function(){
        // Perform some action when the data is ready
    } );
}, 5000 ); // Five second delay

In the above example lets assume that DataModule fetches it's data asynchronously and its really quick.

DiverseAndRemote.com
  • 19,314
  • 10
  • 61
  • 70
  • It sounds like you could consider a Promise rather than an event for this situation where it's a one time occurrence. `dataModule.ready().then(function(...){}); for example. – WiredPrairie Feb 27 '15 at 18:53

2 Answers2

1

What you're asking for isn't a normal event emitter feature. So, you'd have to implement it yourself with two extra steps:

  1. A flag to keep track of whether a given event has fired yet or a means to inquire whether it has yet fired.
  2. A check each time a new listener is added for that given event to see if that event has already fired and if so, you just trigger the listener immediately.

Note, this is exactly what jQuery's .ready() infrastructure does. It adds the above logic itself so any new listener is immediately called when it is installed if the event has already occurred.

And, this obviously assumes that the event is a one-shot type of event (will only ever occur once). And, you need the ability to know if the event has occurred yet.


FYI, you can see something similar implemented here: pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it. The combination of the readyFired flag and the check of document.readyState in that piece of code tells it whether the event has already occurred and, if so, new listeners are called.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

A way to approach this problem is by not relying on events but instead relying on Promises. Using a promise instead of emitting an event changes the code to:

function DataModule(){
    this.data = null;
    this.dataPromise = new Promise( function( fulfill, reject ) {
        request.get( 'http://example.com/api/get/data', function( error, response, body ) {
            if ( error ) {
                reject( error, null );
            }
            else {
                this.data = body;
                fulfill( null, body );
            }
        }.bind( this ) );
    }.bind( this ) );
}

...

var dataModule = new DataModule(); // data fetching happens here.

setTimeout( function(){
    dataModule.dataPromise.then( function( err, data ){
        // Perform some action when the data is ready
    } );
}, 5000 ); // Five second delay
DiverseAndRemote.com
  • 19,314
  • 10
  • 61
  • 70