我正在尝试编写基于websocket rxjs的包装器。
我正在努力解决我对rxjs的理解。
我有一个暂停流,它应该在发生错误时暂停可暂停的缓冲流,并在我从websocket获得“ok”后恢复它们。
不知何故,只有我的可暂停缓冲流的第一个订阅被触发。从那时起,只有队列堆积得更高。
我准备了一个jsbin来重现这个问题。
https://jsbin.com/mafakar/edit?js,console
“msg recived”流只会触发第一个订阅。然后q和观察者开始堆叠。
我不知何故感觉这是关于冷热的观察,但我无法理解这些问题。我将不胜感激任何帮助。
提前谢谢!
答案 0 :(得分:1)
这不是冷/热问题。你在onMessage上做的是订阅,然后处理。 dispose终止序列。 onMessageStream只能订阅一次,例如,在构造函数中:
this.onmessageStream.subscribe(message => console.log('--- msg --- ', message.data));
应删除订阅块,包括dispose。
另外,请注意您在没有计数的情况下使用了replaySubject,这意味着该队列包含所有先前的值。除非这是期望的行为,否则考虑将其更改为.replaySubject(1)
答案 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相对稳定,但由于这些不适合公众消费,因此可以从你的下方改变。