RxJS:如何让一个Observer处理多个Observables?

时间:2015-12-14 20:10:20

标签: javascript reactive-programming rxjs

我正在使用一个调用我实现的函数的框架。我希望将此函数的参数转换为Observable,并通过一系列Observers发送。我以为我可以使用一个主题,但它的表现并不像我预期的那样。

为了澄清,我有类似下面的代码。我认为下面的Option 1会起作用,但到目前为止,我正在寻找Option 2,这似乎不是惯用的。

var eventSubject = new Rx.Subject();
var resultSource = eventSubject.map(processEvent);
var subscription = resultSource.subscribe(
    function(event) {
        console.log("got event", event);
    },
    function(e) {
        log.error(e);
    },
    function() {
        console.log('eventSubject onCompleted');
    }
);

// The framework calls this method
function onEvent(eventArray) {

   var eventSource = Rx.Observable.from(eventArray);

   // Option 1: I thought this would work, but it doesn't
   // eventSource.subscribe(eventSubject);

   // Option 2: This does work, but its obviously clunky
  eventSource.subscribe(
      function(event) {
          log.debug("sending to subject");
          eventSubject.onNext(event);
      },
      function(e) {
          log.error(e);
      },
      function() {
          console.log('eventSource onCompleted');
      }
  );
}

2 个答案:

答案 0 :(得分:3)

正如Brandon已经解释的那样,将eventSubject订阅到另一个observable意味着将eventSubjects onNext,onError和onComplete订阅到onNext,onError和onComplete上的observable。从您的示例中,您似乎只想订阅onNext。

第一个eventSource完成/错误后,你的主题完成/ errros - 你的eventSubject正确地忽略了后续eventSoures对它发出的任何进一步的onNext / onError。

有多种方法可以只订阅任何eventSource的onNext:

  1. 仅手动订阅onNext。

    resultSource = eventSubject
      .map(processEvent);
    
    eventSource.subscribe(
        function(event) {
            eventSubject.onNext(event);
        },
        function(error) {
            // don't subscribe to onError
        },
        function() {
            // don't subscribe to onComplete
        }
    );
    
  2. 使用只处理订阅eventNeource onNext / onError的运算符。这就是布兰登建议的。 请记住,这也订阅了eventSources onError,您似乎不希望这样做。

    resultSource = eventSubject
      .mergeAll()
      .map(processEvent);
    
    eventSubject.onNext(eventSource);
    
  3. 使用不为eventSources onError / onComplete调用eventSubjects onError / onComplete的观察者。您可以简单地将eventSubjects onComplete覆盖为脏黑客,但最好是创建一个新的观察者。

    resultSource = eventSubject
      .map(processEvent);
    
    var eventObserver = Rx.Observer.create(
      function (event) {
        eventSubject.onNext(event);
      }
    );
    
    eventSubject.subscribe(eventObserver);
    

答案 1 :(得分:2)

只是当您将整个Subject订阅到一个可观察对象时,您最终会向该主题订阅该可观察对象的onComplete事件。这意味着当观察完成时,它将完成您的主题。因此,当您获得下一组事件时,他们什么也不做,因为主题已经完成。

一个解决方案正是您所做的。只需将onNext事件订阅到主题。

第二个解决方案,可以说更像“rx like”,将您的传入数据视为可观察的可观察数据,并使用mergeAll展平此可观察流:

var eventSubject = new Rx.Subject(); // observes observable sequences
var resultSource = eventSubject
  .mergeAll() // subscribe to each inner observable as it arrives
  .map(processEvent);
var subscription = resultSource.subscribe(
    function(event) {
        console.log("got event", event);
    },
    function(e) {
        log.error(e);
    },
    function() {
        console.log('eventSubject onCompleted');
    }
);

// The framework calls this method
function onEvent(eventArray) {

   var eventSource = Rx.Observable.from(eventArray);
   // send a new inner observable sequence
   // into the subject
   eventSubject.onNext(eventSource);
}

更新:Here is a running example