Zone.js是angular团队参照NodeJS的Domain,Dart的Zone,为angular 2开发的核心组件。

一开始,我对Zone.js是拒绝的。我们知道类似的 Domain 模块,主要是为了解决异步错误跟踪问题。所以,当我没有太强烈的错误跟踪需求的时候,Zone.js有啥用?

然而execution context不仅仅可以用来跟踪异步错误,还可以做一些猥琐而实用的事情。

先来理解一下 execution context

Zone.current.fork({}).run(function () {
Zone.current.inTheZone = true; setTimeout(function () {
console.log('in the zone: ' + !!Zone.current.inTheZone); // 'in the zone: true'
}, 0);
}); console.log('in the zone: ' + !!Zone.current.inTheZone); // 'in the zone: false'

execution context,我们可以理解成只与当前 fork 出来的Zone实例相关的上下文。

上面的例子很明显,因为只有在 fork 中 Zone 的实例我们才设置了 Zone.current.inTheZone 为 true,所以在外面打印出来的结果是 false。

好神奇,这个怎么做到的呢?

我们想像上面那个过程是同步的,那么发生了什么呢?

const defaultZone = Zone.current
// 生成一个新的Zone
const zone = new Zone()
// 设置当前zone
Zone.current = zone
// 对当前zone设值
Zone.current.inTheZone = true
console.log('in the zone: ' + !!Zone.current.inTheZone)
// 退出当前zone
Zone.current = defaultZone
console.log('in the zone: ' + !!Zone.current.inTheZone)

很好,同步没有什么问题,那么异步怎么办呢?其实很简单,就是在每一个异步入口加一个看门人,就可以了。

const defaultZone = Zone.current
// 生成一个新的Zone
const zone = new Zone()
// 设置当前zone
Zone.current = zone
// 对当前zone设值
Zone.current.inTheZone = true
const anonymousA = function () {
console.log('in the zone: ' + !!Zone.current.inTheZone); // 'in the zone: true'
}
// 给进入异步的函数配发令牌映射到对应zone
anonymousA._zone = zone
// 退出当前zone
Zone.current = defaultZone
setTimeout(() => {
// 函数重新回来,设置当前 zone
Zone.current = anonymousA._zone
anonymousA.call(this)
// 退出当前zone
Zone.current = defaultZone
}, 0)
console.log('in the zone: ' + !!Zone.current.inTheZone)

当然Zone.js实现比上面复杂得多,有兴趣的同学可以看看源代码。

在同一个项目使用不同版本的 jQuery

从上面的例子看,我们可以看到,我们可以在 zone 实例上保存只有该 zone 使用的属性。那么我们在利用Object.defineProperty就可以达成我们的目标了。

  • 我们先简单写一个模块执行器(意思是我才不想管加载的事情):
// 写的巨简单,不要吐槽
!function (win, Zone) {
var map = {};
var noop = {};
var dependence = {};
var alias = {};
var hasSet = {}; // 因为懒,仅支持 define(name, factory),反正只是 demo
function define(name, factory) {
if (typeof factory === 'function') {
map[name] = {
factory: factory,
exports: noop
};
} else {
map[name] = {
exports: factory
};
}
} function require(name) {
var module = map[name]
if (module.exports !== noop) return module.exports;
if (dependence[name]) {
var properties = {};
// 利用Object.defineProperty 组装 window.xxx -> require('xxx') 的映射
Object.keys(dependence[name]).forEach(function (key) {
var res;
if (alias[key]) res = alias[key];
else res = key;
properties[res] = require(key + '@' + dependence[name][key]);
if (!hasSet[res]) {
hasSet[res] = true;
Object.defineProperty(window, res, {
get: function () {
return Zone.current.get(res)
}
});
}
});
// 对每个模块,fork 一个 Zone 实例进行执行
Zone.current.fork({
properties: properties
}).run(function () {
module.exports = module.factory()
});
} else {
module.exports = module.factory();
return module.exports;
}
} function config(opt) {
Object.assign(dependence, opt.dep);
Object.assign(alias, opt.alias);
} require.config = config;
window.define = define;
window.require = require;
}(window, Zone)
  • 试用一下:
// 模拟两个jQuery
define('jquery@1.4', {
version: '1.4',
bind: function () {
console.log('call bind');
}
})
define('jquery@1.8', {
version: '1.8',
on: function () {
console.log('call on');
}
})
// 仅仅打印版本,不做任何事情
function logVersion() {
console.log('version === ', $.version)
}
// 要运行的第一段代码
define('module1', function module1() {
// 使用1.8版本
$.on();
// 证明即使异步调用,这里面的 $ 依然指向正确
setTimeout(logVersion, 100)
})
// 要运行的第二段代码
define('module2', function module2() {
// 使用1.4版本
$.bind();
// 证明即使异步调用,这里面的 $ 依然指向正确
setTimeout(logVersion, 300)
})
// 载入依赖
require.config({
dep: {
module1: {
'jquery': '1.8'
},
module2: {
'jquery': '1.4'
}
},
alias: {
'jquery': '$'
}
})
require('module1')
require('module2')

具体实现参见:(two-different-jquery)[https://github.com/miniflycn/async-technique-you-may-do-not-know/tree/master/two-different-jquery]

更进一步

其实我们可以基于 Zone.js 做一个 Sandbox,则在大型重历史包袱的应用中,可以很好地将多个技术体系共存而不产生恶心的冲突问题。

或者做一个对任意模块依赖注入的方案,对模块之间做完全解耦。

Zone.js 简介 & 抛砖引玉的更多相关文章

  1. zone.js - 暴力之美

    在ng2的开发过程中,Angular团队为我们带来了一个新的库 – zone.js.zone.js的设计灵感来源于Dart语言,它描述JavaScript执行过程的上下文,可以在异步任务之间进行持久性 ...

  2. prototype.js简介

    prototype.js简介 2007-11-21 14:22 prototype.js是一个很强大的Javascript函数库,它可以让你很轻松的使用一些特效,实现AJAX的功能.虽然prototy ...

  3. HTML基础--JS简介、基本语法、类型转换、变量、运算符、分支语句、循环语句、数组、函数、函数调用.avi

    JS简介 1.JavaScript是个什么东西? 它是个脚本语言,需要有宿主文件,它的宿主文件是HTML文件. 2.它与Java什么关系? 没有什么直接的联系,Java是Sun公司(已被Oracle收 ...

  4. 01 Node.js简介, 安装&配置

    Node.js 简介 Node.js 是什么 Node.js 有着强大而灵活的包管理器(node package manager,npm) 目前, 已经有强大第三方工具模块, 例如数据库连接, 网站开 ...

  5. Vue.js简介

    Vue.js简介 Vue.js的作者为Evan You(尤雨溪),任职于Google Creative Lab,虽然是Vue是一个个人项目,但在发展前景上个人认为绝不输于Google的AngularJ ...

  6. Zone.js

    https://github.com/angular/zone.js/ Zone.js

  7. Gulp.js简介

    Gulp.js简介 我们讨论了很多关于怎么减少页面体积,提高重网站性能的方法.有些是操作是一劳永逸的,如开启服务器的gzip压缩,使用适当的图片格式,或删除一些不必要的字符.但有一些任务是每次工作都必 ...

  8. angular 2+ 变化检测系列三(Zone.js在Angular中的应用)

    在系列一中,我们提到Zone.js,Zones是一种执行上下文,它允许我们设置钩子函数在我们的异步任务的开始位置和结束位置,Angular正是利用了这一特性从而实现了变更检测. Zones.js非常适 ...

  9. 《React Native 精解与实战》书籍连载「Node.js 简介与 React Native 开发环境配置」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

随机推荐

  1. com.alibaba.fastjson.JSONObject学习

    JSONObject json = new JSONObject(); //设置json属性,可以是对象,数值 json.put("key",value); //获取json的普通 ...

  2. [2011山东ACM省赛] Sequence (动态规划)

    Sequence Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Given an integer number sequence ...

  3. asp.net 禁用按钮防止重复提交

    按钮设置 1.OnClientClick属性为”this.disabled=true;“ 2.UseSubmitBehavior属性为”false“ 举例如下: <asp:Button ID=& ...

  4. Objective C笔记(第一天)

    • OC语言概述 1.早在20世纪80年代早期,Bard Cox发明了Objective C, 是扩充的C,面向对象的编程语言. 2.NEXTSTEP简称NS a.1985年,Steve Jobs成⽴ ...

  5. 一步一步搭建客服系统 (6) chrome桌面共享

    本文介绍了如何在chrome下用webrtc来实现桌面共.因为必要要用https来访问才行,因此也顺带介绍了如何使用SSL证书. 1 chrome扩展程序 先下载扩展程序示例: https://git ...

  6. Wix 安装部署教程(三)自定义安装界面和行为

    接上一篇自定义安装界面,这篇继续探索,首先介绍下,Wix为我们定义了五种风格,每种风格的UI都是有一定顺序的.我们可以改变安装顺序,也可以完全自定义一个Dialog插入其中.比如Wix_Mondo 风 ...

  7. windows下重启mysql

    其中第二种方法对我这无效,以后再搞清楚! 一.MYSQL服务 我的电脑——(右键)管理——服务与应用程序——服务——MYSQL——开启(停止.重启动) 二.命令行方式 Windows 1.点击“开始” ...

  8. Nagios学习笔记二:Nagios概述

    1.简介 Nagios是插件式的结构,它本身没有任何监控功能,所有的监控都是通过插件进行的,因此其是高度模块化和富于弹性的.Nagios监控的对象可分为两类:主机和服务.主机通常指的是物理主机,如服务 ...

  9. paip.调试js 查看元素事件以及事件断点

    paip.调试js  查看元素事件以及事件断点 ff 26 +firebug 查看不出来.. 360 ,虽然也是chrome 基础,但是开发工具烂阿,也是显示不出来.. 作者Attilax  艾龙,  ...

  10. Leetcode 278 First Bad Version 二分查找(二分下标)

    题意:找到第一个出问题的版本 二分查找,注意 mid = l + (r - l + 1) / 2;因为整数会溢出 // Forward declaration of isBadVersion API. ...