使用Facebook's EventEmitter是一种让延迟侦听器接收已经发出的事件的方法

With Facebook's EventEmitter is there a way to make a late listener receive an event thats already been emitted?

本文关键字:侦听器 延迟 方法 事件 一种 Facebook EventEmitter 使用      更新时间:2024-06-18

如果我有一个正在获取数据的对象,它发出一个"就绪"事件,但另一个对象在该事件被激发后开始侦听该事件,那么有没有直接的方法可以让侦听器接收错过的事件。

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

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

在上面的例子中,我们假设DataModule异步地获取它的数据,而且它非常快。

您想要的不是一个普通的事件发射器功能。所以,你必须自己用两个额外的步骤来实现它:

  1. 用于跟踪给定事件是否已启动的标志,或用于查询该事件是否已触发的手段
  2. 每次为该给定事件添加新的侦听器时都会进行检查,以查看该事件是否已经触发,如果已经触发,则只需立即触发侦听器

注意,这正是jQuery的.ready()基础设施所做的。它本身添加了上述逻辑,因此如果事件已经发生,则在安装任何新侦听器时都会立即调用它。

而且,这显然假设该事件是一次性事件(只会发生一次)。而且,您需要能够知道事件是否已经发生。


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

解决此问题的方法是不依赖事件,而是依赖Promises。使用promise而不是发出事件将代码更改为:

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