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

Commit

Permalink
refactor, not create a new closure _subscribe everytime
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaLiPassion committed Jul 19, 2017
1 parent 7f3d467 commit e90479a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 48 deletions.
1 change: 1 addition & 0 deletions karma-build.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ module.exports = function (config) {
config.files.push('build/lib/zone.js');
config.files.push('build/lib/common/promise.js');
config.files.push('build/lib/common/error-rewrite.js');
config.files.push('build/lib/rxjs/rxjs.js');
config.files.push('build/test/main.js');
};
1 change: 1 addition & 0 deletions karma-dist.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ module.exports = function (config) {
config.files.push('dist/sync-test.js');
config.files.push('dist/task-tracking.js');
config.files.push('dist/wtf.js');
config.files.push('dist/zone-patch-rxjs.js');
config.files.push('build/test/main.js');
};
99 changes: 56 additions & 43 deletions lib/rxjs/rxjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare let define: any;
}
}(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global,
(Rx: any) => {
'use strict';
Zone.__load_patch('rxjs', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
const subscribeSource = 'rxjs.subscribe';
const nextSource = 'rxjs.Subscriber.next';
Expand All @@ -33,6 +34,14 @@ declare let define: any;
Rx.Observable = function() {
Observable.apply(this, arguments);
this._zone = Zone.current;

// patch inner function this._subscribe to check
// SubscriptionZone is same with ConstuctorZone or not
if (this._subscribe && typeof this._subscribe === 'function' && !this._originalSubscribe) {
this._originalSubscribe = this._subscribe;
this._subscribe = _patchedSubscribe;
}

return this;
};

Expand All @@ -42,6 +51,39 @@ declare let define: any;
const lift = Observable.prototype.lift;
const create = Observable.create;

const _patchedSubscribe = function() {
const currentZone = Zone.current;
const _zone = this._zone;

const args = Array.prototype.slice.call(arguments);
const subscriber = args.length > 0 ? args[0] : undefined;
// also keep currentZone in Subscriber
// for later Subscriber.next/error/complete method
if (subscriber && !subscriber._zone) {
subscriber._zone = currentZone;
}
// _subscribe should run in ConstructorZone
// but for performance concern, we should check
// whether ConsturctorZone === Zone.current here
const tearDownLogic = _zone !== Zone.current ?
_zone.run(this._originalSubscribe, this, args) :
this._originalSubscribe.apply(this, args);
if (tearDownLogic && typeof tearDownLogic === 'function') {
const patchedTearDownLogic = function() {
// tearDownLogic should also run in ConstructorZone
// but for performance concern, we should check
// whether ConsturctorZone === Zone.current here
if (_zone && _zone !== Zone.current) {
return _zone.run(tearDownLogic, this, arguments);
} else {
return tearDownLogic.apply(this, arguments);
}
};
return patchedTearDownLogic;
}
return tearDownLogic;
};

// patch Observable.prototype.subscribe
// if SubscripitionZone is different with ConstructorZone
// we should run _subscribe in ConstructorZone and
Expand All @@ -51,43 +93,6 @@ declare let define: any;
const _zone = this._zone;
const currentZone = Zone.current;

// patch inner function this._subscribe to check
// SubscriptionZone is same with ConstuctorZone or not
if (this._subscribe && typeof this._subscribe === 'function') {
this._subscribe._zone = this._zone;
const _subscribe = this._subscribe;
if (_zone) {
this._subscribe = function() {
const args = Array.prototype.slice.call(arguments);
const subscriber = args.length > 0 ? args[0] : undefined;
// also keep currentZone in Subscriber
// for later Subscriber.next/error/complete method
if (subscriber && !subscriber._zone) {
subscriber._zone = currentZone;
}
// _subscribe should run in ConstructorZone
// but for performance concern, we should check
// whether ConsturctorZone === Zone.current here
const tearDownLogic = _zone !== Zone.current ? _zone.run(_subscribe, this, args) :
_subscribe.apply(this, args);
if (tearDownLogic && typeof tearDownLogic === 'function') {
const patchedTearDownLogic = function() {
// tearDownLogic should also run in ConstructorZone
// but for performance concern, we should check
// whether ConsturctorZone === Zone.current here
if (_zone && _zone !== Zone.current) {
return _zone.run(tearDownLogic, this, arguments);
} else {
return tearDownLogic.apply(this, arguments);
}
};
return patchedTearDownLogic;
}
return tearDownLogic;
};
}
}

// if operator is involved, we should also
// patch the call method to save the Subscription zone
if (this.operator && _zone && _zone !== currentZone) {
Expand All @@ -102,12 +107,6 @@ declare let define: any;
};
}
const result = subscribe.apply(this, arguments);
// clean up _subscribe._zone to prevent
// the same _subscribe being used in multiple
// Observable instances.
if (this._subscribe) {
this._subscribe._zone = undefined;
}
// the result is the subscriber sink,
// we save the current Zone here
result._zone = currentZone;
Expand All @@ -118,13 +117,27 @@ declare let define: any;
Observable.prototype.lift = function() {
const observable = lift.apply(this, arguments);
observable._zone = Zone.current;
// patch inner function this._subscribe to check
// SubscriptionZone is same with ConstuctorZone or not
if (this._subscribe && typeof this._subscribe === 'function' && !this._originalSubscribe) {
this._originalSubscribe = this._subscribe;
this._subscribe = _patchedSubscribe;
}

return observable;
};

// patch create method to save ConstructorZone of Observable
Rx.Observable.create = function() {
const observable = create.apply(this, arguments);
observable._zone = Zone.current;
// patch inner function this._subscribe to check
// SubscriptionZone is same with ConstuctorZone or not
if (this._subscribe && typeof this._subscribe === 'function' && !this._originalSubscribe) {
this._originalSubscribe = this._subscribe;
this._subscribe = _patchedSubscribe;
}

return observable;
};

Expand Down
3 changes: 1 addition & 2 deletions test/browser-zone-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@ import '../lib/zone-spec/proxy';
import '../lib/zone-spec/sync-test';
import '../lib/zone-spec/task-tracking';
import '../lib/zone-spec/wtf';
import '../lib/extra/cordova';
import '../lib/rxjs/rxjs';
import '../lib/extra/cordova';
6 changes: 3 additions & 3 deletions test/rxjs/rxjs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
*/

let rxjs;
if (typeof exports === 'object') {
rxjs = require('rxjs');
} else {
if (typeof window !== 'undefined') {
rxjs = (window as any).Rx;
} else if (typeof exports === 'object' && typeof module !== undefined) {
rxjs = require('rxjs');
}
const Observable = rxjs.Observable;
const Subscriber = rxjs.Subscriber;
Expand Down

0 comments on commit e90479a

Please sign in to comment.