问题
I'm capturing events from an application using Rx.Observable.fromEvent in a NodeJS.
These are sent to another server using request (https://www.npmjs.com/package/request).
To avoid a high network load I need to buffer those events at a given timeout between sent requests.
Problem
Using bufferWithTime(200) will keep the node process running and I can't know when the application has finished to close the stream.
Is there any way to use Rx buffers to say:
- When Element 1 is pushed set a timer
- When Element 2 and 3 arrive before the timer expires push them to an array [1, 2, 3] (the buffer)
- When the timer expires, send the [1, 2, 3] array down the pipe.
- If Element 4 came after the timer expires then set a new timer and start all over again.
If no element is pushed then no timer is started which would make the process exit.
My initial approach was:
Rx.Observable
.fromEvent(eventEmitter, 'log')
.bufferWithTime(200) // this is the issue
.map(addEventsToRequestOption)
.map(request)
.flatMap(Promise.resolve)
.subscribe(log('Response received'))
回答1:
A proposed implementation, using the delay operator :
function emits(who){
return function (x) { console.log([who, "emits"].join(" ") + " " + x + " click(s)");};
}
var source = Rx.Observable.fromEvent(document.body, 'click');
console.log("running");
var delayedSource$ = source.delay(1200);
var buffered$ = source
.buffer(function () { return delayedSource$;}).map(function(clickBuffer){return clickBuffer.length;})
buffered$.subscribe(emits("buffer"));
jsbin here : http://jsbin.com/wilurivehu/edit?html,js,console,output
回答2:
You'll probably need to split the stream and use the second part to trigger the first.
var source = Rx.Observable.fromEvent(eventEmitter, 'log');
var closer = source.flatMapFirst(Rx.Observable.timer(2000));
source
.buffer(closer)
.map(addEventsToRequestOption)
.flatMap(function(x) { Promise.resolve(request(x)); })
//I assume this log method returns a function?
.subscribe(log('Response received'));
source.flatMapFirst(Rx.Observable.timer(2000)) is the important line here. It creates an Observable that generates a timer that will trigger after 2000 ms. When the first event comes in it will kick off the timer. flatMapFirst will ignore subsequent events as long as the timer is running. When the timer finally emits it will trigger the buffer to emit its current buffer and start again.
See docs on buffer with a boundary Observable
来源:https://stackoverflow.com/questions/33402737/how-to-create-a-rxjs-buffer-that-groups-elements-in-nodejs-but-that-does-not-rel