Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit ce3f12f

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(rxjs): asap should runGuarded to let error inZone (#884)
* fix(rxjs): asap should runGuarded to let error inZone * add document for how to load rxjs patch
1 parent a733688 commit ce3f12f

File tree

4 files changed

+111
-1
lines changed

4 files changed

+111
-1
lines changed

NON-STANDARD-APIS.md

+58
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,61 @@ for example, if you want to add MediaQuery patch, you should do like this.
103103
<script src="path/zone.js"></script>
104104
<script src="path/webapis-media-query.js"></script>
105105
```
106+
107+
* rxjs
108+
109+
`zone.js` also provide a `rxjs` patch to make sure rxjs Observable/Subscription/Operator run in correct zone.
110+
for detail please refer to [pull request 843](https://github.com/angular/zone.js/pull/843), the following sample code describe the idea.
111+
112+
```
113+
const constructorZone = Zone.current.fork({name: 'constructor'});
114+
const subscriptionZone = Zone.current.fork({name: 'subscription'});
115+
const operatorZone = Zone.current.fork({name: 'operator'});
116+
117+
let observable;
118+
let subscriber;
119+
constructorZone.run(() => {
120+
observable = new Observable((_subscriber) => {
121+
subscriber = _subscriber;
122+
console.log('current zone when construct observable:', Zone.current.name); // will output constructor.
123+
return () => {
124+
console.log('current zone when unsubscribe observable:', Zone.current.name); // will output constructor.
125+
}
126+
});
127+
});
128+
129+
subscriptionZone.run(() => {
130+
observable.subscribe(() => {
131+
console.log('current zone when subscription next', Zone.current.name); // will output subscription.
132+
}, () => {
133+
console.log('current zone when subscription error', Zone.current.name); // will output subscription.
134+
}, () => {
135+
console.log('current zone when subscription complete', Zone.current.name); // will output subscription.
136+
});
137+
});
138+
139+
operatorZone.run(() => {
140+
observable.map(() => {
141+
console.log('current zone when map operator', Zone.current.name); // will output operator.
142+
});
143+
});
144+
```
145+
146+
currently basically all `rxjs` API include
147+
148+
- Observable
149+
- Subscription
150+
- Subscriber
151+
- Operators
152+
- Scheduler
153+
154+
are patched, so they will run in the correct zone.
155+
156+
## Usage.
157+
158+
for example, in angular application, you can load this patch in your `app.module.ts`.
159+
160+
```
161+
import 'zone.js/dist/zone-patch-rxjs';
162+
```
163+

lib/rxjs/rxjs.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ import {rxSubscriber} from 'rxjs/symbol/rxSubscriber';
340340
const action = workArgs.length > 0 ? workArgs[0] : undefined;
341341
const scheduleZone = action && action[zoneSymbol];
342342
if (scheduleZone && scheduleZone !== Zone.current) {
343-
return scheduleZone.run(work, this, arguments);
343+
return scheduleZone.runGuarded(work, this, arguments);
344344
} else {
345345
return work.apply(this, arguments);
346346
}

test/rxjs/rxjs.asap.spec.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import * as Rx from 'rxjs/Rx';
10+
import {asyncTest} from '../test-util';
11+
12+
describe('Scheduler.asap', () => {
13+
let log: string[];
14+
let errorCallback: Function;
15+
const constructorZone: Zone = Zone.root.fork({
16+
name: 'Constructor Zone',
17+
onHandleError: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: Error) => {
18+
log.push('error' + error.message);
19+
const result = delegate.handleError(targetZone, error);
20+
errorCallback && errorCallback();
21+
return false;
22+
}
23+
});
24+
25+
beforeEach(() => {
26+
log = [];
27+
});
28+
29+
it('scheduler asap error should run in correct zone', asyncTest((done: any) => {
30+
let observable: any;
31+
constructorZone.run(() => {
32+
observable = Rx.Observable.of(1, 2, 3).observeOn(Rx.Scheduler.asap);
33+
});
34+
35+
errorCallback = () => {
36+
expect(log).toEqual(['erroroops']);
37+
setTimeout(done, 0);
38+
};
39+
40+
Zone.root.run(() => {
41+
observable
42+
.map((value: number) => {
43+
if (value === 3) {
44+
throw new Error('oops');
45+
}
46+
return value;
47+
})
48+
.subscribe((value: number) => {});
49+
});
50+
}, Zone.root));
51+
});

test/rxjs/rxjs.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
import '../../lib/rxjs/rxjs';
99
import './rxjs.common.spec';
10+
import './rxjs.asap.spec';
1011
import './rxjs.bindCallback.spec';
1112
import './rxjs.bindNodeCallback.spec';
1213
import './rxjs.combineLatest.spec';

0 commit comments

Comments
 (0)