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

Commit

Permalink
fix(rxjs): asap should runGuarded to let error inZone (#884)
Browse files Browse the repository at this point in the history
* fix(rxjs): asap should runGuarded to let error inZone

* add document for how to load rxjs patch
  • Loading branch information
JiaLiPassion authored and mhevery committed Aug 23, 2017
1 parent a733688 commit ce3f12f
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
58 changes: 58 additions & 0 deletions NON-STANDARD-APIS.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,61 @@ for example, if you want to add MediaQuery patch, you should do like this.
<script src="path/zone.js"></script>
<script src="path/webapis-media-query.js"></script>
```

* rxjs

`zone.js` also provide a `rxjs` patch to make sure rxjs Observable/Subscription/Operator run in correct zone.
for detail please refer to [pull request 843](https://github.com/angular/zone.js/pull/843), the following sample code describe the idea.

```
const constructorZone = Zone.current.fork({name: 'constructor'});
const subscriptionZone = Zone.current.fork({name: 'subscription'});
const operatorZone = Zone.current.fork({name: 'operator'});
let observable;
let subscriber;
constructorZone.run(() => {
observable = new Observable((_subscriber) => {
subscriber = _subscriber;
console.log('current zone when construct observable:', Zone.current.name); // will output constructor.
return () => {
console.log('current zone when unsubscribe observable:', Zone.current.name); // will output constructor.
}
});
});
subscriptionZone.run(() => {
observable.subscribe(() => {
console.log('current zone when subscription next', Zone.current.name); // will output subscription.
}, () => {
console.log('current zone when subscription error', Zone.current.name); // will output subscription.
}, () => {
console.log('current zone when subscription complete', Zone.current.name); // will output subscription.
});
});
operatorZone.run(() => {
observable.map(() => {
console.log('current zone when map operator', Zone.current.name); // will output operator.
});
});
```

currently basically all `rxjs` API include

- Observable
- Subscription
- Subscriber
- Operators
- Scheduler

are patched, so they will run in the correct zone.

## Usage.

for example, in angular application, you can load this patch in your `app.module.ts`.

```
import 'zone.js/dist/zone-patch-rxjs';
```

2 changes: 1 addition & 1 deletion lib/rxjs/rxjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ import {rxSubscriber} from 'rxjs/symbol/rxSubscriber';
const action = workArgs.length > 0 ? workArgs[0] : undefined;
const scheduleZone = action && action[zoneSymbol];
if (scheduleZone && scheduleZone !== Zone.current) {
return scheduleZone.run(work, this, arguments);
return scheduleZone.runGuarded(work, this, arguments);
} else {
return work.apply(this, arguments);
}
Expand Down
51 changes: 51 additions & 0 deletions test/rxjs/rxjs.asap.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @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
*/

import * as Rx from 'rxjs/Rx';
import {asyncTest} from '../test-util';

describe('Scheduler.asap', () => {
let log: string[];
let errorCallback: Function;
const constructorZone: Zone = Zone.root.fork({
name: 'Constructor Zone',
onHandleError: (delegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: Error) => {
log.push('error' + error.message);
const result = delegate.handleError(targetZone, error);
errorCallback && errorCallback();
return false;
}
});

beforeEach(() => {
log = [];
});

it('scheduler asap error should run in correct zone', asyncTest((done: any) => {
let observable: any;
constructorZone.run(() => {
observable = Rx.Observable.of(1, 2, 3).observeOn(Rx.Scheduler.asap);
});

errorCallback = () => {
expect(log).toEqual(['erroroops']);
setTimeout(done, 0);
};

Zone.root.run(() => {
observable
.map((value: number) => {
if (value === 3) {
throw new Error('oops');
}
return value;
})
.subscribe((value: number) => {});
});
}, Zone.root));
});
1 change: 1 addition & 0 deletions test/rxjs/rxjs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
import '../../lib/rxjs/rxjs';
import './rxjs.common.spec';
import './rxjs.asap.spec';
import './rxjs.bindCallback.spec';
import './rxjs.bindNodeCallback.spec';
import './rxjs.combineLatest.spec';
Expand Down

0 comments on commit ce3f12f

Please sign in to comment.