diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index b4ea178ba8f..b5725d166f0 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -152,7 +152,25 @@ export function fromEventEmitter(emitter: EventEmitter, eventType: string): E }; } -export function fromPromise(promise: TPromise>): Event { +export function fromPromise(promise: TPromise): Event { + const emitter = new Emitter(); + let shouldEmit = false; + + promise + .then(null, () => null) + .then(() => { + if (!shouldEmit) { + setTimeout(() => emitter.fire(), 0); + } else { + emitter.fire(); + } + }); + + shouldEmit = true; + return emitter.event; +} + +export function delayed(promise: TPromise>): Event { let toCancel: TPromise = null; let listener: IDisposable = null; @@ -275,3 +293,8 @@ export class EventBufferer { buffer.forEach(flush => flush()); } } + +export function stopwatch(event: Event): Event { + const start = new Date().getTime(); + return mapEvent(once(event), _ => new Date().getTime() - start); +} \ No newline at end of file diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts index d79acb3fda0..d3aa7797c46 100644 --- a/src/vs/base/test/common/event.test.ts +++ b/src/vs/base/test/common/event.test.ts @@ -5,10 +5,11 @@ 'use strict'; import * as assert from 'assert'; -import Event, {Emitter, fromEventEmitter, debounceEvent, EventBufferer, once} from 'vs/base/common/event'; +import Event, {Emitter, fromEventEmitter, debounceEvent, EventBufferer, once, fromPromise, stopwatch} 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'); +import {TPromise} from 'vs/base/common/winjs.base'; namespace Samples { @@ -282,4 +283,67 @@ suite('EventBufferer', () => { listener1.dispose(); listener2.dispose(); }); +}); + +suite('fromPromise', () => { + + test('should emit when done', () => { + let count = 0; + + const event = fromPromise(TPromise.as(null)); + event(() => count++); + + assert.equal(count, 0); + + return TPromise.timeout(10).then(() => { + assert.equal(count, 1); + }); + }); + + test('should emit when done - setTimeout', () => { + let count = 0; + + const event = fromPromise(TPromise.timeout(5)); + event(() => count++); + + assert.equal(count, 0); + + return TPromise.timeout(10).then(() => { + assert.equal(count, 1); + }); + }); + + test('should emit when done - setTimeout', () => { + let count = 0; + + const event = fromPromise(TPromise.timeout(10)); + event(() => count++); + + assert.equal(count, 0); + + return TPromise.timeout(0).then(() => { + assert.equal(count, 0); + + return TPromise.timeout(10).then(() => { + assert.equal(count, 1); + }); + }); + }); +}); + +suite('stopwatch', () => { + + test('should emit when done', () => { + const emitter = new Emitter(); + const event = stopwatch(emitter.event); + + return new TPromise(c => { + event(duration => { + assert(duration > 5); + c(null); + }); + + setTimeout(() => emitter.fire(), 5); + }); + }); }); \ No newline at end of file