@JiaLiPassion
A Zone is an execution context that persists across async tasks.
Created by Brian Ford inspired by Dart.
Provide execution context
Provide async task lifecycle interceptable hook
Provide async error handler
Zone.current.fork({name: 'zone', properties: {key: 'value'}})
.run(function() {
// the callback of async operations will remember the context
// when it is scheduled
console.log(Zone.current.name, Zone.current.get('key'));
// zone value
setTimeout(function () {
console.log(Zone.current.name, Zone.current.get('key'));
// zone value
}, 100);
const p = Promise.resolve(1);
p.then(() => {
console.log(Zone.current.name, Zone.current.get('key'));
// zone value
});
});
zoneA.run(() => {
const currentZoneA = Zone.current; // will be zoneA
zoneB.run(() => {
const currentZoneB = Zone.current; // will be zoneB
});
});
const rootZone = Zone.current; // will be <root> zone
console.log(`root zone's name is: ${rootZone.name}`);
// will be <root>
const rootZone = Zone.current; // will be <root> zone
console.log(`root zone's name is: ${rootZone.name}`);
// will be <root>
zone.run(() => {
// Here the onScheduleTask will be invoked
// And onHasTask will also be invoked
setTimeout(function() {
// Here the onInvokeTask will be invoked
console.log('callback invoked');
} // Here the onHasTask will be invoked again,
1000);
});
var zone = Zone.current.fork({
name: 'hook',
onScheduleTask: ...,
onInvokeTask: ....,
onHasTask: ...
});
zone.run(() => {
setTimeout(() => {
console.log('timer callback invoked');
}, 100);
});
https://zone-ebb17.firebaseapp.com/
Zone.current.fork(
{
name: 'error',
onHandleError: (delegate, curr, target, error) => {
logger.error(error);
return delegate.handleError(target, error);
}
}).runGuarded(() => {
setTimeout(() => {
throw new Error('timeout error');
});
setTimeout(() => {
throw new Error('another timeout error');
});
});
const nativeTimeout = window.setTimeout;
window.setTimeout = function(callback) {
const zone = Zone.current;
const wrappedCallback = function() {
zone.onInvokeTask('setTimeout'); // invoke hook
return callback.apply(this, arguments);
}
zone.onScheduleTask('setTimeout'); // schedule hook
nativeTimeout.apply(this, wrappedCallback);
}
Change Detection
AsyncTest
FakeAsyncTest
SyncTest
Error Handling
Debug/Tracing
DOM API
setTimeout
Promise
EventTarget
...
Zone.js
Monkey-Patch
Angular
Timer
Promise
EventTarget
requestAnimationFrame
...
Notification
MediaQuery
UserMedia
...
requestAnimationFrame
__Zone_disable_requestAnimationFrame=true
__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove'];
@HostListener('window:mousemove.nozone')
mouseMoveListener() {
// will not in ngZone.
}
<div (scroll.nozone)="scrollHandler();"></div>
Proposal?
declare let Zone: any;
(window as any)[Zone.__symbol__('setTimeout')](() => {
// will not in zone.
}, 100);
import 'zone.js/dist/zone';
import 'core-js/promise';
import 'zone.js/dist/zone-error';
import 'zone.js/dist/zone-error';
class MyError extends Error {
}
try {
throw new MyError('myError');
} catch (error: Error) {
if (error instanceof MyError) {
// do some special error handling
}
}
(window as any).__Zone_Error_BlacklistedStackFrames_policy = 'disable'; // 'default', 'lazy'
import 'zone.js/dist/zone-mix';
import 'zone.js/dist/zone-patch-electron';
MediaQuery
Notification
RTCPeerConnction
ShadyDom
Cordova
ResizeObserver
SocketIO
UserMedia
Jsonp Helper
Zone.js can be a standalone test library.
import 'zone.js/dist/long-stack-trace';
import 'zone.js/dist/proxy';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async';
import 'zone.js/dist/promise-testing';
import 'zone.js/dist/zone-testing';
import 'zone.js/dist/zone-testing';
describe('zone-testing', () => {
it('fakeAsync', fakeAsyncTest(() => {
tick(100);
discardPeriodicTasks();
flushMicrotasks();
});
it ('async', asyncTest(() => {}));
});
it('should advance Date when tick in fakeAsync', fakeAsync(() => {
const start = Date.now();
tick(100);
const end = Date.now();
expect(end - start).toBe(100);
}));
beforeEach(() => {
jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().uninstall();
});
it('should get date diff correctly', () => { // we don't need fakeAsync here.
// automatically run into fake async zone, because jasmine.clock() is installed.
const start = Date.now();
jasmine.clock().tick(100);
const end = Date.now();
expect(end - start).toBe(100);
});
__zone_symbol__fakeAsyncPatchLock
it('rxjs scheduler should be advanced by tick in fakeAsync', fakeAsync(() => {
observable.delay(1000).subscribe(v => {
result = v;
});
expect(result).toBeNull();
testZoneSpec.tick(1000);
expect(result).toBe('hello');
}));
it('should timeout', async(() => {
setTimeout(() => {}, 10000);
fixture.whenStable(() => {});
}));
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
--Pendng async tasks are: [type: macroTask, source: setTimeout, args: {handleId:3,isPeriodic:false,delay:10000,args:[]}
Web App
JQuery
React
Angular Elements
Zone.js
Zone.js
Zone.js
Miško
Takeshi Kondo