有了Facebook的EventEmitter,有没有办法让迟到的听众收到已经发出的事件?

如果我有一个对象提取数据,它发出一个“就绪”的事件,但另一个对象开始监听该事件已经被触发后,有一个直接的方法,让这个监听器接收错过的事件。

纯粹假设的例子(所以请不要问为什么我会这样做):

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 

在上面的例子中,我们假设DataModuleasynchronous获取数据,并且非常快。

你所要求的不是一个正常的事件发射器function。 所以,你必须自己实现它两个额外的步骤:

  1. 一个标志,以跟踪一个特定的事件是否已经解雇或查询是否已经解雇的手段。
  2. 每次为给定的事件添加一个新的侦听器时,都会检查该事件是否已经触发,如果是,则立即触发侦听器。

请注意,这正是jQuery的.ready()基础结构的function。 它增加了上面的逻辑本身,所以如果事件已经发生,任何新的监听器在安装时立即被调用。

而且,这显然假定事件是一次性事件(将只发生一次)。 而且,你需要知道事件是否发生的能力。


仅供参考,您可以在这里看到类似的实现: 纯JavaScript等价于jQuery的$ .ready()如何在page / dom准备好时调用函数 。 readyFired标志和document.readyState在这段代码中的检查的组合告诉它事件是否已经发生,如果是,则调用新的监听器。

解决这个问题的方法是不依赖于事件,而是依赖于承诺 。 使用承诺而不是发出事件将代码更改为:

 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