foo();
bar();
baz();
function foo() {...}
function bar() {...}
function baz() {...}
要度量其運作時間:
var start,
time = 0;
timer = performance ? performance.now : Date.now;
// start timer
start = timer();
foo();
bar();
baz();
// stop timer
time = timer() - start;
// log time in ms
console.log(Math.floor(time*100) / 100 + 'ms');
然而,如果這些函數是異步執行的函數呢?那麼下列的時間度量代碼,計算出來的duration就不準确了:
function doSomething() {
console.log('Async task');
}
// start timer
start = timer();
foo();
setTimeout(doSomething, 2000);
bar();
baz();
// stop timer
time = timer() - start;
什麼是Angular的zone?
Zones can perform an operation - such as starting or stopping a timer, or saving a stack trace - each time that code enters or exits a zone. They can override methods within our code, or even associate data with individual zones.
zone可以在一段代碼進入或者離開一個zone的時候,執行一個操作,比如開啟或者關閉計時器,或者儲存一個堆棧跟蹤。
Zones are actually a language feature in Dart.
Zone實際上是程式設計語言Dart的一個特性。Dart編譯之後的代碼也是JavaScript,是以我們可以直接在JavaScript裡實作Zone的特性。
Angular項目裡通常都有zone.js的依賴:
function main() {
foo();
setTimeout(doSomething, 2000);
bar();
baz();
}
zone.run(main);
Zones can perform an operation each time our code enters or exits a zone.
var myZoneSpec = {
beforeTask: function () {
console.log('Before task');
},
afterTask: function () {
console.log('After task');
}
};
var myZone = zone.fork(myZoneSpec);
myZone.run(main);
// Logs:
// Before task
// After task
// Before task
// Async task
// After task
It turns out that there are a few other hooks. In fact, those aren’t just hooks, but monkey-patched methods on the global scope.
全局scope裡還存在稱為monke-patched的方法。
when we call setTimeout() we actually call Zone.setTimeout(), which in turn creates a new zone using zone.fork() in which the given handler is executed.
當我們調用setTimeout時,我們實際上調用的是Zone.setTimeout, 後者會使用zone.fork(),建立新的zone,而setTimeout裡的函數,就運作在這個新fork出來的zone裡面。
And that’s why our hooks are executed as well, because the forked zone in which the handler will be executed, simply inherits from the parent zone.
而hook執行兩次的原因,是因為函數運作于fork出來的zone裡面,而後者繼承了parent zone的hook.
Zone.js重載了下列方法,并且以hook的方式提供給應用開發人員使用:
Zone.setInterval()
Zone.alert()
Zone.prompt()
Zone.requestAnimationFrame()
Zone.addEventListener()
Zone.removeEventListener()
We might wonder why methods like alert() and prompt() are patched as well. As mentioned earlier, those patched methods are hooks at the same time. We can change and extend them by forking a zone exactly the same way we did with beforeTask and afterTask. This turns out to be super powerful, because we can intercept calls to alert() and prompt() and change their behaviour when we write tests.
類似alert和prompt方法和其他方法一樣同時被patch,在fork一個新zone時,可以傳入我們自己的實作進去,在寫單元測試代碼時尤其有用。
用于度量一段異步執行代碼執行時間的profilingZone的實作源代碼: