问题
This RxJava buffer example (with marble chart!) describes the desired result perfectly:
collect items in buffers during the bursty periods and emit them at the end of each burst, by using the debounce operator to emit a buffer closing indicator to the buffer operator
Edit: having reviewed How to create a RxJS buffer that groups elements in NodeJS but that does not rely on forever running interval?, my issue appears related to using a Subject as opposed to straight Observable.
Using the socket stream to generate window close events (as follows) results in 2 sockets opened and no events streaming out:
ws = Rx.DOM.fromWebSocket(wsURI, null, wsOpenObserver, wsCloseObserver);
var closer = ws.flatMapFirst(Rx.Observable.timer(250));
ws.buffer(closer)
.subscribe(function(e) { console.log(e, 'socket messages');});
回答1:
Summarizing the findings issue here :
Rx.DOM.fromWebSocketreturns aRx.subjectwhich wraps around the websocket. That subject is made from one observer and one observable (vianew Rx.Subject(observer, observable). From what I understood, that observer allows to write to the socket via itsonNextmethod, while the observable allows to read from the socket.- you always read that subjects are hot sources, but apparently here that only means that the observer will immediately push its value to the subject which here pushes it to the socket. In normal cases(
new Rx.Subject()), the default observer and observable are so that the observable listens to the observer, hence the default observable is hot. Here however, the observable is a cold source and then any subscription will reexecute the callback creating another websocket. Hence the creation of two sockets. - this does not happen for instance with
Rx.dom.fromEventbecause the created (cold) observable is shared (viapublish().refCount()). - thus by doing the same here, the duplication issue can be solved. That means in this particular case, use in your code
ws = Rx.DOM.fromWebSocket(wsURI, null, wsOpenObserver, wsCloseObserver).share();,sharebeing an alias forpublish().refCount(). - I have to wonder whether that behaviour of
Rx.DOM.fromWebSocketshould be reported as a bug
Code for both methods:
- https://github.com/Reactive-Extensions/RxJS-DOM/blob/master/src/dom/websocket.js
- https://github.com/Reactive-Extensions/RxJS-DOM/blob/master/src/events/fromevent.js
回答2:
You can pass an Observable directly to the buffer operator just like the RxJava version:
source.buffer(source.debounce(150))
is valid. See here.
The alternative syntax using the selector method that you show will invoke that method every time a buffer closes and then subscribe to the Observable it produces.
Also the debounce in the RxJava example is emitting the result of the buffer operator, it does not emit accumulated results by default.
来源:https://stackoverflow.com/questions/33495390/how-to-buffer-stream-using-fromwebsocket-subject