除非明确的支出不同 否则所有内容基于Angular version >= 2.x
在NG-Conf2014 Brian 有一个很好的介绍ZONE的视频
PS:请使用正确的上网方式,他讲的是我们如何改变处理异步的方式。你应该去瞅一眼,他只有15分钟长,虽然API可能和现在不一样,但是语义(semantics)和底层概念是相同的,在这篇文章中,我们将一起探究ZONE的工作原理。
让我们回顾一下ZONE,就如Brian所说的,它基本上就是一个执行上下文(an execution context)的异步操作,这对于我们处理和分析错误等非常有用,但这到底意味着什么呢?
为了了解它的执行上下文,我们需要去了解ZONE去试图解决的问题是什么,废话少说,上代码
foo();
bar();
baz();
function foo() {...}
function bar() {...}
function baz() {...}
很正常的3个function,foo,bar和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');
但是,我们也有很多异步的工作要去做,比如用AJAX从服务端取得数据,或者我们只是想安排之后的工作,正如它的名称 asynchronously. 这基本上意味着,这些操作不会考虑我们是否知道。再看看下面这个代码
function doSomething() {
console.log('Async task');
}
// start timer
start = timer();
foo();
setTimeout(doSomething, 2000);
bar();
baz();
// stop timer
time = timer() - start;
我们又加了一个代码方法,但是他是异步的,这对我们分析代码有什么影响,好吧,没啥影响。
但是有一个附加的操作,他需要较长的世界去执行这段代码,当我们实际的时间去执行setTimeout的时候,返回的不是整体的一部分,这是因为这个异步操作被添加到事件队列(event queue)中去了,在到达那个时机的时候去完成事件循环(event loop)。
如果你不知道这是啥东西,你可能要去看一下这里,或者JS红宝书中的高级定时器部分。
那我们要怎么解决这个问题呢。我们需要的是基本挂钩,使我们能够随时在这样的异步任务执行情况分析的一些代码。当然,我们也许可以创建并启动用于手动加载每个异步操作的个体定时器,但作为异步操作被添加到代码序列,那样相当杂乱。
这正是ZONE的要解决的问题。ZONE可以执行的操作-如启动或停止计时器,或保存堆栈,跟踪-每一个代码进入或退出某个区域的时间。他们可以在我们的代码中重写方法,甚至个别区域数据相关联。
ZONE实际上是一个Dart语言特征。然而,由于Dart也只是编译成JavaScript,我们可以实现在JavaScript中相同的功能了。布莱恩(Brian)(我前面提到的家伙)做了这一点。他创造zone.js作为Zones的一个端口(port)的JavaScript,这也是angular2的依赖。之前,我们来看看我们如何可以分析我们的代码样本区,让我们先讨论如何创建Zones。
只要将zong.js引入我们的网站,我们就能获得全局的zone对象。zone带有一个方法run()是检测在该区域执行的方法。换句话说,如果我们想在一个ZONE中运行我们的代码,我们可以这么做:
function main() {
foo();
setTimeout(doSomething, 2000);
bar();
baz();
}
zone.run(main);
很容易,但是这样和之前的写法没啥两样。我们需要写更多的代码,让我们的在另一个上下文环境中运行,就像我们之前说的,ZONE可以在我们进入或者或者推出上下文环境的时候进行操作。
为了建立这些挂钩,我们需要fork当前的ZONE。分叉区返回一个新的区域,基本上由“父”区域中继承。然而,分叉区还允许我们扩展了返还区的行为。我们可以通过调用fork一个区域.fork()上zone的对象。下面是可能的样子:
zone.js - 暴力之美 直接看这个吧。