-
Notifications
You must be signed in to change notification settings - Fork 25.6k
/
event_emitter.ts
144 lines (130 loc) Β· 4.39 KB
/
event_emitter.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/// <reference types="rxjs" />
import {Subject, Subscription} from 'rxjs';
/**
* Use in directives and components to emit custom events synchronously
* or asynchronously, and register handlers for those events by subscribing
* to an instance.
*
* @usageNotes
*
* In the following example, a component defines two output properties
* that create event emitters. When the title is clicked, the emitter
* emits an open or close event to toggle the current visibility state.
*
* ```
* @Component({
* selector: 'zippy',
* template: `
* <div class="zippy">
* <div (click)="toggle()">Toggle</div>
* <div [hidden]="!visible">
* <ng-content></ng-content>
* </div>
* </div>`})
* export class Zippy {
* visible: boolean = true;
* @Output() open: EventEmitter<any> = new EventEmitter();
* @Output() close: EventEmitter<any> = new EventEmitter();
*
* toggle() {
* this.visible = !this.visible;
* if (this.visible) {
* this.open.emit(null);
* } else {
* this.close.emit(null);
* }
* }
* }
* ```
*
* Access the event object with the `$event` argument passed to the output event
* handler:
*
* ```
* <zippy (open)="onOpen($event)" (close)="onClose($event)"></zippy>
* ```
*
* ### Notes
*
* Uses Rx.Observable but provides an adapter to make it work as specified here:
* https://github.com/jhusain/observable-spec
*
* Once a reference implementation of the spec is available, switch to it.
*
* @publicApi
*/
export class EventEmitter<T> extends Subject<T> {
// TODO: mark this as internal once all the facades are gone
// we can't mark it as internal now because EventEmitter exported via @angular/core would not
// contain this property making it incompatible with all the code that uses EventEmitter via
// facades, which are local to the code and do not have this property stripped.
/**
* Internal
*/
__isAsync: boolean; // tslint:disable-line
/**
* Creates an instance of this class that can
* deliver events synchronously or asynchronously.
*
* @param isAsync When true, deliver events asynchronously.
*
*/
constructor(isAsync: boolean = false) {
super();
this.__isAsync = isAsync;
}
/**
* Emits an event containing a given value.
* @param value The value to emit.
*/
emit(value?: T) { super.next(value); }
/**
* Registers handlers for events emitted by this instance.
* @param generatorOrNext When supplied, a custom handler for emitted events.
* @param error When supplied, a custom handler for an error notification
* from this emitter.
* @param complete When supplied, a custom handler for a completion
* notification from this emitter.
*/
subscribe(generatorOrNext?: any, error?: any, complete?: any): Subscription {
let schedulerFn: (t: any) => any;
let errorFn = (err: any): any => null;
let completeFn = (): any => null;
if (generatorOrNext && typeof generatorOrNext === 'object') {
schedulerFn = this.__isAsync ? (value: any) => {
setTimeout(() => generatorOrNext.next(value));
} : (value: any) => { generatorOrNext.next(value); };
if (generatorOrNext.error) {
errorFn = this.__isAsync ? (err) => { setTimeout(() => generatorOrNext.error(err)); } :
(err) => { generatorOrNext.error(err); };
}
if (generatorOrNext.complete) {
completeFn = this.__isAsync ? () => { setTimeout(() => generatorOrNext.complete()); } :
() => { generatorOrNext.complete(); };
}
} else {
schedulerFn = this.__isAsync ? (value: any) => { setTimeout(() => generatorOrNext(value)); } :
(value: any) => { generatorOrNext(value); };
if (error) {
errorFn =
this.__isAsync ? (err) => { setTimeout(() => error(err)); } : (err) => { error(err); };
}
if (complete) {
completeFn =
this.__isAsync ? () => { setTimeout(() => complete()); } : () => { complete(); };
}
}
const sink = super.subscribe(schedulerFn, errorFn, completeFn);
if (generatorOrNext instanceof Subscription) {
generatorOrNext.add(sink);
}
return sink;
}
}