学习ng2,从zonejs开始(非官方翻译) ----angular2系列(一)
Zone是什么:
官方解释:zone.js为JavaScript提供了执行上下文,可以在异步任务之间进行持久性传递。
最开始我一直没理解到这句话,学习过程中我也因为自己的一些失误而一直纠结徘徊,情况是这样的:
首先我在本地用npm安装了zone.js,然后我就打开了zone.js的github ———— zoneJs
这一切都很正常,然后看着readme,跟着demo写下去。下面这样:
然后问题来了,当我运行的时候,结果根本就不是官方显示的那样,我打开调试器,发现全局根本没有 window.zone ,却只有window.Zone,
难道是需要new一个?好吧,我new一个。结果还是不对。 好吧,我去看源码,发现原型根本就没有beforeTask,afterTask,而后看了很久源码,
发现run和fork方法的执行逻辑, 根本就不像是官方教程那样。
最后我终于找到问题了:
是版本问题,我看的教程是0.5版本,看的源码确是0.6,本地安装的版本也是默认最新的0.6。
好吧,我承认我英文不好,没看到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社区做出的贡献!
相关文章
- Caffe学习系列(12):不同格式下计算图片的均值和caffe.proto
- caffe学习系列(5):激活层介绍
- caffe学习系列(1):图像数据转换成db(leveldb/lmdb)文件
- 机器学习入门04 - 使用TensorFlow的起始步骤 (First Steps with TensorFlow)
- 【J2ME 2D 游戏开发系列】◣HIMI游戏开发启蒙教程◢JAVA零基础学习J2ME游戏开发全过程!
- rman命令学习-tina(上)
- java学习之maven
- 【NLP】蓦然回首:谈谈学习模型的评估系列文章(二)
- 机器学习数学系列(2):微分选讲
- 深度学习实验系列(1)
- OpenGL学习笔记 - 计算机图形学和现代图形API
- Python视觉深度学习系列教程 第三卷 第9章 Kaggle竞赛:情绪识别
- Python视觉深度学习系列教程 第二卷 第3章 理解rank-1&rank-5精度
- Python视觉深度学习系列教程 第一卷 第5章 图像分类数据集
- Python视觉深度学习系列教程 第一卷 第21章 案例:使用CNN破解验证码
- Python视觉深度学习系列教程 第一卷 第15章 MiniVGGNet:深入了解CNN
- 使用Java程序消费SAP Leonardo的机器学习API
- 【玩转数据系列二】机器学习应用没那么难,这次教你玩心脏病预测
- Atitit 学习的本质 团队管理与培训的本质 attilax总结 v2
- Python语言学习:创建/删除文件/文件夹、获取当前文件/文件夹路径(系统环境路径/目录)、获取当前文件夹下的所有子文件路径等代码(os系列用法)实现之详细攻略
- 如何使用小数据集对大模型进行微调(迁移学习)-微迁移
- 【深度学习系列】卷积神经网络CNN原理详解(一)——基本原理(1)
- Java学习路线-6:Annotation注解、多态和抽象类
- Javascript中String对象的的简单学习
- 《TPM原理及应用指南》学习 —— TPM执行环境1(2)
- 基因表达谱学习[转载]
- python学习===如何理解python中的return
- 【youcans 的图像处理学习课】11. 形态学图像处理(上)
- 集成学习-Stacking算法
- 转:TensorFlow学习系列之八:什么是数据流图?
- 如何选择和训练机器学习模型?
- LFS学习系列7 — II.构建准备 —— 3. 包和补丁(2)
- LFS学习系列6 — II.构建准备 —— 3. 包和补丁(1)
- Scheme学习系列O:启动篇
- Scheme学习系列一 :源码安装Gambit