Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript RxJs动态添加来自另一个EventEmitter的事件_Javascript_Http Live Streaming_Rxjs - Fatal编程技术网

Javascript RxJs动态添加来自另一个EventEmitter的事件

Javascript RxJs动态添加来自另一个EventEmitter的事件,javascript,http-live-streaming,rxjs,Javascript,Http Live Streaming,Rxjs,我有一个来自EventEmitter的可观测数据,它实际上只是一个http连接,流式事件 有时,我必须断开与底层流的连接并重新连接。我不知道如何用rxjs处理这个问题 我不确定我是否可以完成一个源代码,然后动态地将其他“源代码”添加到源代码中,或者我是否必须做一些与最底层类似的事情 var Rx = require('rx'), EventEmitter = require('events').EventEmitter; var eventEmitter = new EventEm

我有一个来自EventEmitter的可观测数据,它实际上只是一个http连接,流式事件

有时,我必须断开与底层流的连接并重新连接。我不知道如何用rxjs处理这个问题

我不确定我是否可以完成一个源代码,然后动态地将其他“源代码”添加到源代码中,或者我是否必须做一些与最底层类似的事情

var Rx = require('rx'),
    EventEmitter = require('events').EventEmitter;

  var eventEmitter = new EventEmitter();
  var eventEmitter2 = new EventEmitter();

  var source = Rx.Observable.fromEvent(eventEmitter, 'data')

  var subscription = source.subscribe(function (data) {
    console.log('data: ' + data);
  });

  setInterval(function() {
    eventEmitter.emit('data', 'foo');
  }, 500);

  // eventEmitter stop emitting data, underlying connection closed
  // now attach seconds eventemitter (new connection)

  // something like this but obvouisly doesn't work
  source
    .fromEvent(eventEmitter2, 'data')
Puesdo代码这是我正在做的更多事情,我在关闭第一个流连接之前创建第二个流连接,所以我不会“丢失”任何数据。在这里,我不知道如何停止Observable而不“丢失”记录,因为onNext由于缓冲区而没有被调用

  var streams = [], notifiers = [];

  // create initial stream
  createNewStream();

  setInterval(function() {
    if (params of stream have changed) createNewStream();
  }, $1minutes / 3);

  function createNewStream() {
    var stream = new eventEmitterStream();

    stream.once('connected', function() {
      stopOthers();

      streams.push(stream);
      createSource(stream, 'name', 'id');
    });
  }

  function stopOthers() {
    while(streams.length > 0) {
      streams.pop().stop(); // stop the old stream
    }

    while(notifiers.length > 0) {
      // if i call this, the buffer may lose records, before onNext() called
      //notifiers.pop()(Rx.Notification.createOnCompleted());
    }
  }

  function createObserver(tag) {
    return Rx.Observer.create(
      function (x) {
        console.log('Next: ', tag, x.length, x[0], x[x.length-1]);
      },
      function (err) {
        console.log('Error: ', tag, err);
      },
      function () {
        console.log('Completed', tag);
      });
  }

  function createSource(stream, event, id) {
    var source = Rx.Observable
      .fromEvent(stream, event)
      .bufferWithTimeOrCount(time, max);

    var subscription = source.subscribe(createObserver(id));
    var notifier = subscription.toNotifier();
    notifiers.push(notifier);
  }

首先也是最重要的一点,您需要确保可以从以前“死”的发射器中删除所有侦听器。否则,您将创建一个泄漏的应用程序

似乎知道EventEmitter已死亡的唯一方法是观察频率,除非您有一个在错误或完成时触发的事件(用于断开连接)。后者更受欢迎

无论如何,Rx的秘密在于确保将您的数据流创建和拆卸包装在您的可观察的中。如果将发射器的创建包装在observable中,并将其拆下,您将能够使用类似于
retry
操作符的很棒的东西来重新创建该observable

因此,如果您无法知道它是否已死亡,并且您想重新连接它,您可以使用以下方法:

// I'll presume you have some function to get an EventEmitter that 
// is already set up
function getEmitter() {
  var emitter = new EventEmitter();
  setInterval(function(){
    emitter.emit('data', 'foo');
  }, 500)
  return emitter;
}


var emitterObservable = Observable.create(function(observer) {
  // setup the data stream
  var emitter = getEmitter();
  var handler = function(d) {
    observer.onNext(d);
  };
  emitter.on('data', handler);

  return function() {
    // tear down the data stream in your disposal function
    emitter.removeListener('on', handler);
  };
});

// Now you can do Rx magic!
emitterObservable
  // if it doesn't emit in 700ms, throw a timeout error
  .timeout(700)
  // catch all* errors and retry
  // this means the emitter will be torn down and recreated 
  // if it times out!
  .retry()
  // do something with the values
  .subscribe(function(x) { console.log(x); });

*注意:重试捕获所有错误,因此您可能希望在其上方添加一个
catch
,以处理非超时错误。由您决定。

阅读文档中有关缓冲和背压的部分。@BenjaminGruenbaum我已经阅读了文档。一般页面和特定于方法的页面上都有许多示例。这就是我得到缓冲区方法的地方。是否有您认为最有帮助的特定页面或部分。感谢您让我知道
重试
。我现在正在尝试。仅供参考:当我运行时,我得到
范围错误:超过了最大调用堆栈大小
。我想这只是因为没有从
getEmitter
返回任何东西。我试图通过重新连接来实现的行为是在轮到我时“重新连接”,而不会“丢失数据”。这需要先连接到另一个eventEmitter,然后断开第一个。有趣的是,我需要更多的上下文,连接之间会丢失哪些数据?因此数据是以恒定流的形式输入的,因此如果断开连接,则在断开连接和重新连接时会丢失数据。所以我的“方法”,我试图做的是先连接第二个连接,然后断开第一个连接。这样,我就不会“失去”任何东西。