rxjs pausableBuffered多个订阅

时间:2016-10-17 19:18:55

标签: javascript rxjs

我正在尝试编写基于websocket rxjs的包装器。

我正在努力解决我对rxjs的理解。

我有一个暂停流,它应该在发生错误时暂停可暂停的缓冲流,并在我从websocket获得“ok”后恢复它们。

不知何故,只有我的可暂停缓冲流的第一个订阅被触发。从那时起,只有队列堆积得更高。

我准备了一个jsbin来重现这个问题。

https://jsbin.com/mafakar/edit?js,console

“msg recived”流只会触发第一个订阅。然后q和观察者开始堆叠。

我不知何故感觉这是关于冷热的观察,但我无法理解这些问题。我将不胜感激任何帮助。

提前谢谢!

2 个答案:

答案 0 :(得分:1)

这不是冷/热问题。你在onMessage上做的是订阅,然后处理。 dispose终止序列。 onMessageStream只能订阅一次,例如,在构造函数中:

this.onmessageStream.subscribe(message => console.log('--- msg --- ', message.data));

应删除订阅块,包括dispose。

另外,请注意您在没有计数的情况下使用了replaySubject,这意味着该队列包含所有先前的值。除非这是期望的行为,否则考虑将其更改为.replaySubject(1)

这是working jsbin

答案 1 :(得分:1)

由于@Meir指出订阅块中的dispose是否定的,因为它的行为是非确定性的。一般来说,我会避免使用Subjects而是依赖工厂方法。您可以在此处查看重构版本:https://jsbin.com/popixoqafe/1/edit?js,console

快速细分变化:

class WebSocketWrapper {
  // Inject the pauser from the external state
  constructor(pauser) {

    // Input you need to keep as a subject
    this.input$ = new Rx.Subject();

    // Create the socket
    this._socket = this._connect();      

    // Create a stream for the open event
    this.open$ = Rx.Observable.fromEvent(this._socket, 'open');

    // This concats the external pauser with the 
    // open event. The result is a pauser that won't unpause until
    // the socket is open.
    this.pauser$ = Rx.Observable.concat(
      this.open$.take(1).map(true)
      pauser || Rx.Observable.empty()
    )
      .startWith(false);

    // subscribe and buffer the input
    this.input$
      .pausableBuffered(this.pauser$)
      .subscribe(msg => this._socket.send(msg));

    // Create a stream around the message event
    this.message$ = Rx.Observable.fromEvent(this._socket, 'message')

      // Buffer the messages
      .pausableBuffered(this.pauser$)

      // Create a shared version of the stream and always replay the last
      // value to new subscribers
      .shareReplay(1);
  }

  send(request) {
    // Push to input
    this.input$.onNext(request);
  }

  _connect() {
    return new WebSocket('wss://echo.websocket.org');
  }
}

另外,您还应该避免依赖于source等内部变量,这些变量不适合外部消费。虽然RxJS 4相对稳定,但由于这些不适合公众消费,因此可以从你的下方改变。