X Tutup
Skip to content

Commit 019cb41

Browse files
NathanWalkeralxhub
authored andcommitted
fix(EventEmitter): resolve onError and onComplete asynchronously
closes #4443
1 parent b4de41b commit 019cb41

File tree

3 files changed

+78
-21
lines changed

3 files changed

+78
-21
lines changed

modules/angular2/src/facade/async.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {global, isPresent} from 'angular2/src/facade/lang';
1+
import {global, isPresent, noop} from 'angular2/src/facade/lang';
22
// We make sure promises are in a separate file so that we can use promises
33
// without depending on rxjs.
44
import {PromiseWrapper, Promise, PromiseCompleter} from 'angular2/src/facade/promise';
@@ -27,6 +27,8 @@ export class ObservableWrapper {
2727
// TODO(vsavkin): when we use rxnext, try inferring the generic type from the first arg
2828
static subscribe<T>(emitter: any, onNext: (value: T) => void, onError?: (exception: any) => void,
2929
onComplete: () => void = () => {}): Object {
30+
onError = (typeof onError === "function") && onError || noop;
31+
onComplete = (typeof onComplete === "function") && onComplete || noop;
3032
return emitter.subscribe({next: onNext, error: onError, complete: onComplete});
3133
}
3234

@@ -117,20 +119,39 @@ export class EventEmitter<T> extends Subject<T> {
117119
next(value: any) { super.next(value); }
118120

119121
subscribe(generatorOrNext?: any, error?: any, complete?: any): any {
122+
let schedulerFn;
123+
let errorFn = (err: any) => null;
124+
let completeFn = () => null;
125+
120126
if (generatorOrNext && typeof generatorOrNext === 'object') {
121-
let schedulerFn = this._isAsync ?
122-
(value) => { setTimeout(() => generatorOrNext.next(value)); } :
123-
(value) => { generatorOrNext.next(value); };
124-
return super.subscribe(schedulerFn,
125-
(err) => generatorOrNext.error ? generatorOrNext.error(err) : null,
126-
() => generatorOrNext.complete ? generatorOrNext.complete() : null);
127+
schedulerFn = this._isAsync ? (value) => { setTimeout(() => generatorOrNext.next(value)); } :
128+
(value) => { generatorOrNext.next(value); };
129+
130+
if (generatorOrNext.error) {
131+
errorFn = this._isAsync ? (err) => { setTimeout(() => generatorOrNext.error(err)); } :
132+
(err) => { generatorOrNext.error(err); };
133+
}
134+
135+
if (generatorOrNext.complete) {
136+
completeFn = this._isAsync ? () => { setTimeout(() => generatorOrNext.complete()); } :
137+
() => { generatorOrNext.complete(); };
138+
}
127139
} else {
128-
let schedulerFn = this._isAsync ? (value) => { setTimeout(() => generatorOrNext(value)); } :
129-
(value) => { generatorOrNext(value); };
130-
131-
return super.subscribe(schedulerFn, (err) => error ? error(err) : null,
132-
() => complete ? complete() : null);
140+
schedulerFn = this._isAsync ? (value) => { setTimeout(() => generatorOrNext(value)); } :
141+
(value) => { generatorOrNext(value); };
142+
143+
if (error) {
144+
errorFn =
145+
this._isAsync ? (err) => { setTimeout(() => error(err)); } : (err) => { error(err); };
146+
}
147+
148+
if (complete) {
149+
completeFn =
150+
this._isAsync ? () => { setTimeout(() => complete()); } : () => { complete(); };
151+
}
133152
}
153+
154+
return super.subscribe(schedulerFn, errorFn, completeFn);
134155
}
135156
}
136157

modules/angular2/src/facade/lang.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ export function isDate(obj): boolean {
126126
return obj instanceof Date && !isNaN(obj.valueOf());
127127
}
128128

129+
export function noop() {}
130+
129131
export function stringify(token): string {
130132
if (typeof token === 'string') {
131133
return token;

modules/angular2/test/core/facade/async_spec.ts

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,42 @@ export function main() {
6262
expect(called).toBe(false);
6363
});
6464

65-
it('delivers events asynchronously', inject([AsyncTestCompleter], (async) => {
66-
var e = new EventEmitter();
67-
var log = [];
68-
ObservableWrapper.subscribe(e, (x) => {
69-
log.push(x);
70-
expect(log).toEqual([1, 3, 2]);
71-
async.done();
72-
});
65+
it("delivers next and error events asynchronously", inject([AsyncTestCompleter], (async) => {
66+
let log = [];
67+
ObservableWrapper.subscribe(emitter,
68+
(x) => {
69+
log.push(x);
70+
expect(log).toEqual([1, 3, 5, 2]);
71+
},
72+
(err) => {
73+
log.push(err);
74+
expect(log).toEqual([1, 3, 5, 2, 4]);
75+
async.done();
76+
});
7377
log.push(1);
74-
ObservableWrapper.callEmit(e, 2);
78+
ObservableWrapper.callEmit(emitter, 2);
7579
log.push(3);
80+
ObservableWrapper.callError(emitter, 4);
81+
log.push(5);
82+
}));
83+
84+
it("delivers next and complete events asynchronously", inject([AsyncTestCompleter], (async) => {
85+
let log = [];
86+
ObservableWrapper.subscribe(emitter,
87+
(x) => {
88+
log.push(x);
89+
expect(log).toEqual([1, 3, 5, 2]);
90+
},
91+
null, () => {
92+
log.push(4);
93+
expect(log).toEqual([1, 3, 5, 2, 4]);
94+
async.done();
95+
});
96+
log.push(1);
97+
ObservableWrapper.callEmit(emitter, 2);
98+
log.push(3);
99+
ObservableWrapper.callComplete(emitter);
100+
log.push(5);
76101
}));
77102

78103
it('delivers events synchronously', () => {
@@ -110,6 +135,15 @@ export function main() {
110135
expect(ObservableWrapper.isObservable(e)).toBe(true);
111136
});
112137

138+
it('should subscribe to EventEmitters', () => {
139+
let e = new EventEmitter(false);
140+
141+
ObservableWrapper.subscribe(e, (val) => {});
142+
143+
ObservableWrapper.callEmit(e, 1);
144+
ObservableWrapper.callComplete(e);
145+
});
146+
113147
});
114148

115149
// See ECMAScript 6 Spec 25.4.4.1

0 commit comments

Comments
 (0)
X Tutup