Skip to content

Commit

Permalink
feat: add method fromEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
yisraelx committed Mar 4, 2018
1 parent 78acfa7 commit 41248df
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 1 deletion.
1 change: 1 addition & 0 deletions modules/-all/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export { default as forEachParallel } from '@promises/for-each-parallel/add';
export { default as forEachRightSeries } from '@promises/for-each-right-series/add';
export { default as forEachSeries } from '@promises/for-each-series/add';
export { default as fromCallback } from '@promises/from-callback/add';
export { default as fromEvent, IFromEventOptions, IEmitterLike } from '@promises/from-event/add';
export * from '@promises/interfaces';
export { default as isPromise } from '@promises/is-promise/add';
export { default as keys } from '@promises/keys/add';
Expand Down
1 change: 1 addition & 0 deletions modules/-all/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@promises/for-each-right-series": "^0.2.0",
"@promises/for-each-series": "^0.2.0",
"@promises/from-callback": "NEXT-PLACEHOLDER",
"@promises/from-event": "NEXT-PLACEHOLDER",
"@promises/interfaces": "^0.2.0",
"@promises/is-promise": "^0.2.0",
"@promises/keys": "^0.2.0",
Expand Down
3 changes: 2 additions & 1 deletion modules/-constructor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export {default as Promises} from '@promises/core';
export {default as create} from '@promises/create/add';
export {default as delay} from '@promises/delay/add';
export {default as exec} from '@promises/exec/add';
export { default as fromCallback } from '@promises/from-callback/add';
export {default as fromCallback} from '@promises/from-callback/add';
export {default as fromEvent, IFromEventOptions, IEmitterLike} from '@promises/from-event/add';
export * from '@promises/interfaces';
export {default as isPromise} from '@promises/is-promise/add';
export {default as promisify, IPromisifyOptions} from '@promises/promisify/add';
Expand Down
1 change: 1 addition & 0 deletions modules/-constructor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@promises/delay": "^0.2.0",
"@promises/exec": "^0.2.0",
"@promises/from-callback": "NEXT-PLACEHOLDER",
"@promises/from-event": "NEXT-PLACEHOLDER",
"@promises/interfaces": "^0.2.0",
"@promises/is-promise": "^0.2.0",
"@promises/parallel": "^0.2.0",
Expand Down
25 changes: 25 additions & 0 deletions modules/from-event/add.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Promises from '@promises/core';
import fromEvent, { IEmitterLike, IFromEventOptions } from './';

Promises._setOnConstructor('fromEvent', fromEvent);

export {IEmitterLike, IFromEventOptions} from './';
export default fromEvent;

declare module '@promises/core' {
namespace Promises {
/**
* @example
*
* ```typescript
* let emitter: EventEmitter = new EventEmitter()
* Promises.fromEvent(emitter, 'foo').then((data) => {
* console.log(data); // data => 'bar'
* });
*
* emitter.emit('foo', 'bar');
* ```
*/
export function fromEvent<R>(emitter: IEmitterLike, event: string, options?: IFromEventOptions): Promises<R>;
}
}
44 changes: 44 additions & 0 deletions modules/from-event/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @module @promises/from-event
* @copyright © 2017 Yisrael Eliav <yisraelx@gmail.com> (https://github.com/yisraelx)
* @license MIT
*/

export type IEmitterLike = { addEventListener, removeEventListener } | { addListener, removeListener } | { on, off };

export interface IFromEventOptions {
multi?: boolean;
reject?: boolean;
}

/**
* @example
*
* ```typescript
* let emitter: EventEmitter = new EventEmitter()
* Promise.race([
* fromEvent(emitter, 'foo'),
* fromEvent(emitter, 'error', {reject: true})
* ]).catch((error) => {
* console.log(error); // error => 'some error'
* });
*
* emitter.emit('error', 'some error');
* ```
*/
function fromEvent<R>(emitter: IEmitterLike, event: string, options: IFromEventOptions = {}): Promise<R> {
let {multi = false, reject: rejection = false} = options;

let add = (emitter as any).addEventListener || (emitter as any).addListener || (emitter as any).on;
let remove = (emitter as any).removeEventListener || (emitter as any).removeListener || (emitter as any).off;

return new Promise((resolve, reject) => {
add.call(emitter, event, function handler(...args: any[]) {
remove.call(emitter, event, handler);
let data: R = multi ? args : args[0];
rejection ? reject(data) : resolve(data);
});
});
}

export default fromEvent;
37 changes: 37 additions & 0 deletions modules/from-event/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "@promises/from-event",
"version": "NEXT-PLACEHOLDER",
"description": "From Event is package from Promises library",
"main": "es5.js",
"browser": "umd.min.js",
"module": "index.js",
"es2015": "index.js",
"typings": "index.d.ts",
"bundle": "bundle.min.js",
"author": {
"name": "Yisrael Eliev",
"url": "https://github.com/yisraelx",
"email": "yisraelx@gmail.com"
},
"license": "MIT",
"keywords": [
"promise",
"promises",
"utility",
"modules",
"async",
"await",
"deferred"
],
"homepage": "https://github.com/yisraelx/promises#readme",
"repository": {
"type": "git",
"url": "https://github.com/yisraelx/promises.git"
},
"bugs": {
"url": "https://github.com/yisraelx/promises/issues"
},
"optionalDependencies": {
"@promises/core": "^0.2.0"
}
}
55 changes: 55 additions & 0 deletions test/from-event.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import fromEvent from '@promises/from-event';

class Emitter {

_events: { [key: string]: Function[] } = {};

on(event: string, handler) {
if (!this._events[event]) this._events[event] = [];
if (this._events[event].indexOf(handler) === -1) this._events[event].push(handler);
}

off(event: string, handler) {
let handlers = this._events[event] || [];
let index = handlers.indexOf(handler);
if (index !== -1) handlers.splice(index, 1);
}

emit(event: string, ...args: any[]) {
let handlers = this._events[event] || [];
let {length} = handlers;
for (let i = 0; i < length; i++) {
let handler = handlers[i];
handler(...args);
}
}
}

describe('fromEvent', () => {

it('should be resolve on emit', () => {
let emitter = new Emitter();
fromEvent(emitter, 'foo').then((data) => {
expect(data).toBe('bar');
});
emitter.emit('foo', 'bar');
});

it('should be reject on emit', () => {
let emitter = new Emitter();
fromEvent(emitter, 'error', {reject: true}).then(() => {
throw 'resolve';
}).catch((error) => {
expect(error).toBe('reject');
});
emitter.emit('error', 'reject');
});

it('should be resolve multi on emit', () => {
let emitter = new Emitter();
fromEvent(emitter, 'color', {multi: true}).then((args) => {
expect(args).toEqual(['red', 'blue']);
});
emitter.emit('color', 'red', 'blue');
});
});

0 comments on commit 41248df

Please sign in to comment.