diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 4ec7191ec3b204ee8cc0de40d1f26cccc6a2ebd9..95ae379649da2f4a84f938d759acb76dd18e6bc6 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -375,7 +375,7 @@ export function stopwatch(event: Event): Event { * // 4 * ``` */ -export function buffer(event: Event): Event { +export function buffer(event: Event, nextTick = false): Event { let buffer: T[] = []; let listener = event(e => { if (buffer) { @@ -385,6 +385,11 @@ export function buffer(event: Event): Event { } }); + const flush = () => { + buffer.forEach(e => emitter.fire(e)); + buffer = null; + }; + const emitter = new Emitter({ onFirstListenerAdd() { if (!listener) { @@ -394,8 +399,11 @@ export function buffer(event: Event): Event { onFirstListenerDidAdd() { if (buffer) { - buffer.forEach(e => emitter.fire(e)); - buffer = null; + if (nextTick) { + setTimeout(flush); + } else { + flush(); + } } }, diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts index 9e014a13b8fd9af322451c2e10086fe797a27906..0251118b73f1f4e30c1fa96ff9d9ad47f23c162b 100644 --- a/src/vs/base/test/common/event.test.ts +++ b/src/vs/base/test/common/event.test.ts @@ -5,7 +5,7 @@ 'use strict'; import * as assert from 'assert'; -import Event, {Emitter, fromEventEmitter, debounceEvent, EventBufferer, once, fromPromise, stopwatch} from 'vs/base/common/event'; +import Event, {Emitter, fromEventEmitter, debounceEvent, EventBufferer, once, fromPromise, stopwatch, buffer} from 'vs/base/common/event'; import {IDisposable} from 'vs/base/common/lifecycle'; import {EventEmitter} from 'vs/base/common/eventEmitter'; import Errors = require('vs/base/common/errors'); @@ -211,144 +211,197 @@ suite('Event',function(){ }); }); -suite('EventBufferer', () => { +suite('Event utils', () => { - test('should not buffer when not wrapped', () => { - const bufferer = new EventBufferer(); - const counter = new Samples.EventCounter(); - const emitter = new Emitter(); - const event = bufferer.wrapEvent(emitter.event); - const listener = event(counter.onEvent, counter); + suite('EventBufferer', () => { - assert.equal(counter.count, 0); - emitter.fire(); - assert.equal(counter.count, 1); - emitter.fire(); - assert.equal(counter.count, 2); - emitter.fire(); - assert.equal(counter.count, 3); + test('should not buffer when not wrapped', () => { + const bufferer = new EventBufferer(); + const counter = new Samples.EventCounter(); + const emitter = new Emitter(); + const event = bufferer.wrapEvent(emitter.event); + const listener = event(counter.onEvent, counter); - listener.dispose(); - }); + assert.equal(counter.count, 0); + emitter.fire(); + assert.equal(counter.count, 1); + emitter.fire(); + assert.equal(counter.count, 2); + emitter.fire(); + assert.equal(counter.count, 3); - test('should buffer when wrapped', () => { - const bufferer = new EventBufferer(); - const counter = new Samples.EventCounter(); - const emitter = new Emitter(); - const event = bufferer.wrapEvent(emitter.event); - const listener = event(counter.onEvent, counter); + listener.dispose(); + }); - assert.equal(counter.count, 0); - emitter.fire(); - assert.equal(counter.count, 1); + test('should buffer when wrapped', () => { + const bufferer = new EventBufferer(); + const counter = new Samples.EventCounter(); + const emitter = new Emitter(); + const event = bufferer.wrapEvent(emitter.event); + const listener = event(counter.onEvent, counter); - bufferer.bufferEvents(() => { + assert.equal(counter.count, 0); emitter.fire(); assert.equal(counter.count, 1); + + bufferer.bufferEvents(() => { + emitter.fire(); + assert.equal(counter.count, 1); + emitter.fire(); + assert.equal(counter.count, 1); + }); + + assert.equal(counter.count, 3); emitter.fire(); - assert.equal(counter.count, 1); + assert.equal(counter.count, 4); + + listener.dispose(); }); - assert.equal(counter.count, 3); - emitter.fire(); - assert.equal(counter.count, 4); + test('once', () => { + const emitter = new Emitter(); - listener.dispose(); - }); + let counter1 = 0, counter2 = 0, counter3 = 0; - test('once', () => { - const emitter = new Emitter(); + const listener1 = emitter.event(() => counter1++); + const listener2 = once(emitter.event)(() => counter2++); + const listener3 = once(emitter.event)(() => counter3++); - let counter1 = 0, counter2 = 0, counter3 = 0; + assert.equal(counter1, 0); + assert.equal(counter2, 0); + assert.equal(counter3, 0); - const listener1 = emitter.event(() => counter1++); - const listener2 = once(emitter.event)(() => counter2++); - const listener3 = once(emitter.event)(() => counter3++); + listener3.dispose(); + emitter.fire(); + assert.equal(counter1, 1); + assert.equal(counter2, 1); + assert.equal(counter3, 0); - assert.equal(counter1, 0); - assert.equal(counter2, 0); - assert.equal(counter3, 0); + emitter.fire(); + assert.equal(counter1, 2); + assert.equal(counter2, 1); + assert.equal(counter3, 0); - listener3.dispose(); - emitter.fire(); - assert.equal(counter1, 1); - assert.equal(counter2, 1); - assert.equal(counter3, 0); + listener1.dispose(); + listener2.dispose(); + }); + }); - emitter.fire(); - assert.equal(counter1, 2); - assert.equal(counter2, 1); - assert.equal(counter3, 0); + suite('fromPromise', () => { - listener1.dispose(); - listener2.dispose(); - }); -}); + test('should emit when done', () => { + let count = 0; -suite('fromPromise', () => { + const event = fromPromise(TPromise.as(null)); + event(() => count++); - test('should emit when done', () => { - let count = 0; + assert.equal(count, 0); + + return TPromise.timeout(10).then(() => { + assert.equal(count, 1); + }); + }); - const event = fromPromise(TPromise.as(null)); - event(() => count++); + test('should emit when done - setTimeout', () => { + let count = 0; - assert.equal(count, 0); + const event = fromPromise(TPromise.timeout(5)); + event(() => count++); - return TPromise.timeout(10).then(() => { - assert.equal(count, 1); + assert.equal(count, 0); + + return TPromise.timeout(10).then(() => { + assert.equal(count, 1); + }); }); - }); - test('should emit when done - setTimeout', () => { - let count = 0; + test('should emit when done - setTimeout', () => { + let count = 0; - const event = fromPromise(TPromise.timeout(5)); - event(() => count++); + const event = fromPromise(TPromise.timeout(10)); + event(() => count++); - assert.equal(count, 0); + assert.equal(count, 0); + + return TPromise.timeout(0).then(() => { + assert.equal(count, 0); - return TPromise.timeout(10).then(() => { - assert.equal(count, 1); + return TPromise.timeout(10).then(() => { + assert.equal(count, 1); + }); + }); }); }); - test('should emit when done - setTimeout', () => { - let count = 0; + suite('stopwatch', () => { - const event = fromPromise(TPromise.timeout(10)); - event(() => count++); + test('should emit', () => { + const emitter = new Emitter(); + const event = stopwatch(emitter.event); - assert.equal(count, 0); + return new TPromise((c, e) => { + event(duration => { + try { + assert(duration > 0); + } catch (err) { + e(err); + } - return TPromise.timeout(0).then(() => { - assert.equal(count, 0); + c(null); + }); - return TPromise.timeout(10).then(() => { - assert.equal(count, 1); + setTimeout(() => emitter.fire(), 10); }); }); }); -}); -suite('stopwatch', () => { + suite('buffer', () => { - test('should emit', () => { - const emitter = new Emitter(); - const event = stopwatch(emitter.event); + test('should buffer events', () => { + const result = []; + const emitter = new Emitter(); + const event = emitter.event; + const bufferedEvent = buffer(event); - return new TPromise((c, e) => { - event(duration => { - try { - assert(duration > 0); - } catch (err) { - e(err); - } + emitter.fire(1); + emitter.fire(2); + emitter.fire(3); + assert.deepEqual(result, []); - c(null); - }); + const listener = bufferedEvent(num => result.push(num)); + assert.deepEqual(result, [1,2,3]); + + emitter.fire(4); + assert.deepEqual(result, [1,2,3,4]); - setTimeout(() => emitter.fire(), 10); + listener.dispose(); + emitter.fire(5); + assert.deepEqual(result, [1,2,3,4]); + }); + + test('should buffer events on next tick', () => { + const result = []; + const emitter = new Emitter(); + const event = emitter.event; + const bufferedEvent = buffer(event, true); + + emitter.fire(1); + emitter.fire(2); + emitter.fire(3); + assert.deepEqual(result, []); + + const listener = bufferedEvent(num => result.push(num)); + assert.deepEqual(result, []); + + return TPromise.timeout(10).then(() => { + emitter.fire(4); + assert.deepEqual(result, [1,2,3,4]); + + listener.dispose(); + emitter.fire(5); + assert.deepEqual(result, [1,2,3,4]); + }); }); }); + }); \ No newline at end of file