@samitouri / QOS-React / commits / 7c13ea2f2b

Improve bridge batching logic

Fixes #132.

Sophie Alpert committed Apr 10, 2019 at 16:31 UTC 7c13ea2f2b9aa11859c44f01dfeef29d402b276c
1 file changed +28 -24
src/bridge.js
+28 -24
@@ -13,7 +13,6 @@ type Message = {|
13
14 export default class Bridge extends EventEmitter {
15 _messageQueue: Array<any> = [];
16 - _time: number | null = null;
16 _timeoutID: TimeoutID | null = null;
17 _wall: Wall;
18
@@ -28,34 +27,39 @@ export default class Bridge extends EventEmitter {
27 }
28
29 send(event: string, payload: any, transferable?: Array<any>) {
31 - const time = this._time;
32 -
33 - if (time === null) {
34 - this._wall.send(event, payload, transferable);
35 - this._time = Date.now();
36 - } else {
37 - this._messageQueue.push(event, payload, transferable);
38 -
39 - const now = Date.now();
40 - if (now - time > BATCH_DURATION) {
41 - this._flush();
42 - } else {
43 - this._timeoutID = setTimeout(this._flush, BATCH_DURATION);
44 - }
30 + // When we receive a message:
31 + // - we add it to our queue of messages to be sent
32 + // - if there hasn't been a message recently, we set a timer for 0 ms in
33 + // the future, allowing all messages created in the same tick to be sent
34 + // together
35 + // - if there *has* been a message flushed in the last BATCH_DURATION ms
36 + // (or we're waiting for our setTimeout-0 to fire), then _timeoutID will
37 + // be set, and we'll simply add to the queue and wait for that
38 +
39 + this._messageQueue.push(event, payload, transferable);
40 + if (!this._timeoutID) {
41 + this._timeoutID = setTimeout(this._flush, 0);
42 }
43 }
44
45 _flush = () => {
49 - while (this._messageQueue.length) {
50 - this._wall.send.apply(this._wall, this._messageQueue.splice(0, 3));
51 - }
46 + clearTimeout(this._timeoutID);
47 + this._timeoutID = null;
48
53 - if (this._timeoutID !== null) {
54 - clearTimeout(this._timeoutID);
55 - this._timeoutID = null;
56 - }
49 + if (this._messageQueue.length) {
50 + for (let i = 0; i < this._messageQueue.length; i += 3) {
51 + this._wall.send(
52 + this._messageQueue[i],
53 + this._messageQueue[i + 1],
54 + this._messageQueue[i + 2],
55 + );
56 + }
57 + this._messageQueue.length = 0;
58
58 - this._messageQueue = [];
59 - this._time = null;
59 + // Check again for queued messages in BATCH_DURATION ms. This will keep
60 + // flushing in a loop as long as messages continue to be added. Once no
61 + // more are, the timer expires.
62 + this._timeoutID = setTimeout(this._flush, BATCH_DURATION);
63 + }
64 };
65 }