-
Notifications
You must be signed in to change notification settings - Fork 74
/
fromevent.ts
106 lines (95 loc) · 3.6 KB
/
fromevent.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { AsyncIterableX } from './asynciterablex.js';
import { fromEventPattern } from './fromeventpattern.js';
import { isFunction } from '../util/isiterable.js';
type CommonEventHandler = (...args: any[]) => void;
/** @ignore */
export interface OnOffEventEmitter {
on(event: string | symbol, listener: CommonEventHandler): this;
off(event: string | symbol, listener: CommonEventHandler): this;
}
/** @ignore */
export interface NodeEventEmitter {
addListener(event: string | symbol, listener: CommonEventHandler): this;
removeListener(event: string | symbol, listener: CommonEventHandler): this;
}
/** @ignore */
export type EventListenerOptions =
| {
capture?: boolean;
passive?: boolean;
once?: boolean;
}
| boolean;
/** @ignore */
export type EventedTarget = EventTarget | OnOffEventEmitter | NodeEventEmitter;
function isMessagePortEventEmitter(obj: any): obj is OnOffEventEmitter {
return !!obj && isFunction(obj.on) && isFunction(obj.off);
}
function isNodeEventEmitter(obj: any): obj is NodeEventEmitter {
return !!obj && isFunction(obj.addListener) && isFunction(obj.removeListener);
}
function isEventTarget(obj: any): obj is EventTarget {
return !!obj && isFunction(obj.addEventListener) && isFunction(obj.removeEventListener);
}
export function fromEvent<TSource>(obj: EventedTarget, eventName: string): AsyncIterableX<TSource>;
export function fromEvent<TSource>(
obj: EventedTarget,
eventName: string,
resultSelector: (...args: any[]) => TSource
): AsyncIterableX<TSource>;
export function fromEvent<TSource>(
obj: EventedTarget,
eventName: string,
options: EventListenerOptions
): AsyncIterableX<TSource>;
export function fromEvent<TSource>(
obj: EventedTarget,
eventName: string,
options: EventListenerOptions,
resultSelector: (...args: any[]) => TSource
): AsyncIterableX<TSource>;
/**
* Converts an event emitter event into an async-iterable stream.
*
* @template TSource The type of elements in the emitter stream.
* @param {EventedTarget} obj The object that emits the events to turn into an async-iterable.
* @param {string} type The name of the event to listen for creation of the async-iterable.
* @param {EventListenerOptions} [options] The options for listening to the events such as capture, passive and once.
* @param {(...args: any[]) => TSource} [resultSelector] The result selector for the event.
* @returns {AsyncIterableX<TSource>} An async-iterable sequence created from the events emitted from the evented target.
*/
export function fromEvent<TSource>(
obj: EventedTarget,
type: string,
options?: EventListenerOptions | ((...args: any[]) => TSource),
resultSelector?: (...args: any[]) => TSource
): AsyncIterableX<TSource> {
if (isFunction(options)) {
resultSelector = options;
options = undefined;
}
if (isEventTarget(obj)) {
const target = <EventTarget>obj;
return fromEventPattern<TSource>(
(h) => target.addEventListener(type, <EventListener>h, options as EventListenerOptions),
(h) => target.removeEventListener(type, <EventListener>h, options as EventListenerOptions),
resultSelector
);
} else if (isMessagePortEventEmitter(obj)) {
const target = <OnOffEventEmitter>obj;
return fromEventPattern<TSource>(
(h) => target.on(type, h),
(h) => target.off(type, h),
resultSelector
);
} else if (isNodeEventEmitter(obj)) {
const target = <NodeEventEmitter>obj;
return fromEventPattern<TSource>(
(h) => target.addListener(type, h),
(h) => target.removeListener(type, h),
resultSelector
);
} else {
throw new TypeError('Unsupported event target');
}
}