@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 hook
Provide error handler for async operations
Zone.current.fork({name: 'zone', properties: {key: 'value'}})
.run(function() {
setTimeout(function () {
console.log(Zone.current.name, Zone.current.get('key'));
// zone value
}, 100);
setTimeout(function() {
console.log(Zone.current.name, Zone.current.get('key'));
// zone value
}, 200);
Promise.resolve(1).then(() => {
console.log(Zone.current.name, Zone.current.get('key'));
// zone value
});
});
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);
}
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');
});
});
NgZone
Change Detection
AsyncTest
FakeAsyncTest
SyncTest
Error Handling
Debug/Tracing
TaskTrackingZone
LongStackTraceZone
Timer
Promise
EventTarget
...
requestAnimationFrame
(window as any).__Zone_disable_requestAnimationFrame = true;
(window as any).__Zone_disable_customElements = true;
// recommended variable name
__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove'];
// deprecated variable name
// __zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove'];
// ngZone.runOutsideAngular(() => {});
declare let Zone: any;
(window as any)[Zone.__symbol__('setTimeout')](() => {
// will not in zone.
}, 100);
ZoneAwarePromise
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';
import 'zone.js/dist/zone-mix';
import 'zone.js/dist/zone-patch-electron';
MediaQuery
Notification
RTCPeerConnction
ShadyDom
Cordova
ResizeObserver
SocketIO
UserMedia
Jsonp Helper
will support performance api later
it('should advance Date with 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', () => {
// automatically run into fake async zone,
const start = Date.now();
jasmine.clock().tick(100);
const end = Date.now();
expect(end - start).toBe(100);
});
__zone_symbol__fakeAsyncAutoFakeAsyncWhenClockPatched
import 'zone.js/dist/zone-patch-rxjs-fake-async';
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:[]}
<script src="zone.js/dist/zone-evergreen.js"
type="module"></script>
<script src="zone.js/dist/zone.js" nomodule></script>
<div (click)="doSomethingElse()">
<button (click)="doSomething()">click me</button>
</div>
platformBrowserDynamic()
.bootstrapModule(
AppModule,
{
ngZoneEventCoalescing: true
}
)
button.addEventListener('click', click1);
button.addEventListener('click', click2);
button.addEventListener('mousedown', mousedown1);
const clickListeners = button.eventListeners('click');
// will get click1 and click2
button.removeAllListeners('click');
// will remove click1 and click2
button.removeAllListeners();
// will remove all listeners for all events