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.
What you're asking for isn't a normal event emitter feature. So, you'd have to implement it yourself with two extra steps:
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.
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