From 2a8bab87182a9d47adc2e3c949d48a6f5f9772db Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 15 Sep 2016 16:50:41 +0200 Subject: [PATCH] event: buffer --- src/vs/base/common/event.ts | 70 +++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 8c9b1f456e7..4ec7191ec3b 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -26,6 +26,7 @@ export default Event; export interface EmitterOptions { onFirstListenerAdd?: Function; + onFirstListenerDidAdd?: Function; onLastListenerRemove?: Function; } @@ -72,11 +73,19 @@ export class Emitter { if (!this._callbacks) { this._callbacks = new CallbackList(); } - if (this._options && this._options.onFirstListenerAdd && this._callbacks.isEmpty()) { + + const firstListener = this._callbacks.isEmpty(); + + if (firstListener && this._options && this._options.onFirstListenerAdd) { this._options.onFirstListenerAdd(this); } + this._callbacks.add(listener, thisArgs); + if (firstListener && this._options && this._options.onFirstListenerDidAdd) { + this._options.onFirstListenerDidAdd(this); + } + let result: IDisposable; result = { dispose: () => { @@ -263,11 +272,11 @@ enum EventDelayerState { * ``` * const emitter: Emitter; * const delayer = new EventDelayer(); - * const delayedEvent = delayer.delay(emitter.event); + * const delayedEvent = delayer.wrapEvent(emitter.event); * * delayedEvent(console.log); * - * delayer.wrap(() => { + * delayer.bufferEvents(() => { * emitter.fire(); // event will not be fired yet * }); * @@ -342,4 +351,59 @@ export function chain(event: Event): IChainableEvent { export function stopwatch(event: Event): Event { const start = new Date().getTime(); return mapEvent(once(event), _ => new Date().getTime() - start); +} + +/** + * Buffers the provided event until a first listener comes + * along, at which point fire all the events at once and + * pipe the event from then on. + * + * ```typescript + * const emitter = new Emitter(); + * const event = emitter.event; + * const bufferedEvent = buffer(event); + * + * emitter.fire(1); + * emitter.fire(2); + * emitter.fire(3); + * // nothing... + * + * const listener = bufferedEvent(num => console.log(num)); + * // 1, 2, 3 + * + * emitter.fire(4); + * // 4 + * ``` + */ +export function buffer(event: Event): Event { + let buffer: T[] = []; + let listener = event(e => { + if (buffer) { + buffer.push(e); + } else { + emitter.fire(e); + } + }); + + const emitter = new Emitter({ + onFirstListenerAdd() { + if (!listener) { + listener = event(e => emitter.fire(e)); + } + }, + + onFirstListenerDidAdd() { + if (buffer) { + buffer.forEach(e => emitter.fire(e)); + buffer = null; + } + }, + + onLastListenerRemove() { + listener.dispose(); + listener = null; + } + }); + + return emitter.event; } \ No newline at end of file -- GitLab