学习ng2,从zonejs开始(非官方翻译) ----angular2系列(一)

Zone是什么html

  官方解释:zone.js为JavaScript提供了执行上下文,能够在异步任务之间进行持久性传递。git

最开始我一直没理解到这句话,学习过程当中我也由于本身的一些失误而一直纠结徘徊,状况是这样的:github

  首先我在本地用npm安装了zone.js,而后我就打开了zone.js的github ———— zoneJsnpm

这一切都很正常,而后看着readme,跟着demo写下去。下面这样:浏览器

 

而后问题来了,当我运行的时候,结果根本就不是官方显示的那样,我打开调试器,发现全局根本没有 window.zone ,却只有window.Zone,app

难道是须要new一个?好吧,我new一个。结果仍是不对。 好吧,我去看源码,发现原型根本就没有beforeTask,afterTask,然后看了好久源码,异步

发现run和fork方法的执行逻辑, 根本就不像是官方教程那样。ide

最后我终于找到问题了:函数

 

是版本问题,我看的教程是0.5版本,看的源码确是0.6,本地安装的版本也是默认最新的0.6。oop

好吧,我认可我英文很差,没看到DEPRECATED 这个单词。

安装0.5,那么这个问题解决了。之后当心...

 

言归正传, 咱们在demo中去理解:

zone.fork().run(function () {
  zone.inTheZone = true;

  setTimeout(function () {
    console.log('in the zone 1: ' + !!zone.inTheZone);
  }, 0);
});

console.log('in the zone 2: ' + !!zone.inTheZone);

//console
//'in the zone 2: false'
//'in the zone 1: true'

在demo的基础上,我加上了数字编号 'in the zone ' + '1' or '2',  固然他们的执行顺序,没什么问题。问题就是为何第一次输出是false?

执行run的时候,zone.inTheZone已经变成true了,这个全局对象的属性应该已是true了啊!

readme下面还有一句话:Note that the function delayed by setTimeout stays inside the zone

延迟方法已经停留在zone内部,这是什么意思?这时候我又改变了一下代码:

zone.fork().run(function () {
        zone.inTheZone = true;
        console.log(zone);
        console.log('1: ' + !!zone.inTheZone);
        setTimeout(function () {
          console.log(zone);
          console.log('2: ' + !!zone.inTheZone);
        }, 0);
      });
console.log(zone);
console.log('3: ' + !!zone.inTheZone);

结果:

 

注意zone的 id , 全局zone原来一直在变化, 他们的父子关系是以下:父->子,id:1 -> id:2 -> id:3

全局zone最开始默认id为1。

zone.fork.run的时候,zone就建立了一个新zone任务,id为2

执行setTimeout的时候,又建立了一个id为3。

无论运行什么任务,其实全局zone都在变化,全部任务都在全局zone下执行了。

这就是官方说的:zone.js采用猴子补丁(Monkey-patched)的暴力方式将JavaScript中的异步任务都包裹了一层,使得这些异步任务都将运行在zone的上下文中。

 

好吧,虽说zone在变化,为何第一次输出是false,如今解释可能就简单的多了。还得看下源码:

源码告诉咱们:在执行当前zone任务的时候,全局zone指向当前任务的zone对象,执行完毕后全局zone还原到前一个zone任务。

 

那么,执行run的时候,全局zone是id2的任务,执行完毕后 id2的zone的inTheZone属性变成true,全局zone又变成id1的zone对象,

然后立刻输出了 id1 的 inTheZone 属性,这个时候 id1 并无定义inTheZone,因此是false。

最后执行了 id3 的任务,为何又输出是true呢,如今只有 id2 的 inTheZone 才会是true啊!

缘由是zone会继承父zone,如图:

 

这样这个输出结果为何是这样就算搞清楚了。

 

可是它又是如何给setTimeout添加zone任务的呢,由于run执行时并无办法执行延迟操做,异步操做会被添加到浏览器的事件队列,在下一次事件循环(event loops)中才会被执行。

setTimeout怎么被zone给捕获的呢。这也是zoneJs比较核心的一个地方:

zone修改了原生setTimeout,咱们在控制器里输入setTimeout,结果以下:

function() {
    return global.zone[setName].apply(global.zone, arguments);
}

固然被修改的还有下面这些延迟事件(截图自源码):

全部延迟事件都将被zone捕获。

 

zone还提供了执行先后的钩子函数(hook):

  • onZoneCreated:产生一个新的zone对象时的钩子函数。zone.fork也会产生一个继承至基类zone的新zone,造成一个独立的zone上下文;
  • beforeTask:zone Task执行前的钩子函数;
  • afterTask:zone Task执行完成后的钩子函数;
  • onError:zone运行Task时候的异常钩子函数;

demo以下:

var profilingZone = (function () {
        var time = 0,
            timer = performance ?
                        performance.now.bind(performance) :
                        Date.now.bind(Date);
        return {
          beforeTask: function () {
            console.log("beforeTask");
            this.start = timer();
          },
          afterTask: function () {
            console.log("afterTask");
            time += timer() - this.start;
          },
          time: function () {
            return Math.floor(time*100) / 100 + 'ms';
          },
          reset: function () {
            time = 0;
          }
        };
      }());

      zone.fork(profilingZone).run(function(){
        console.log(profilingZone.time());
        setTimeout(function(){console.log(profilingZone.time())}, 200);

      });

/***console***/
//
beforeTask
//0ms
//afterTask

//beforeTask
//1.8ms
//
afterTask

这些钩子函数能帮助咱们,任务先后拦截并作一些想要的操做,无论是延迟或不延迟的任务都将被拦截。

 

zoneJs官网已经不推荐0.5版本了,可是zone0.6几乎算没有文档。

readme上的: See the new API here

打开这个here,看起来确实也很难理解

zonejs 0.6改动较大,封装性很强,写法变化较大,还有待研究

目前ng2已经在升级0.6了,最终修改完毕后,到底会是什么样子,还不得知,目前我看到的0.6的源码里,好像已经没有beforeTask这些钩子函数了。

总之0.6的代码太难以理解了。我没怎么看懂,它能够作什么。

目测ng2要发布正式版,还须要时间。

固然这篇博客仍是参考了,破狼的文章 zone.js - 暴力之美

很是感谢他为ng社区作出的贡献!

相关文章
相关标签/搜索