代码改变世界

[置顶]Javascript & Java & C++系列

2013-01-24 23:29 by Justany_WhiteSnow, 801 阅读, 0 推荐, 收藏, 编辑
摘要:放太多在置顶不好,就放在这里了。 阅读全文

[置顶]基于jQuery 2.0的源代码分析

2013-01-19 20:15 by Justany_WhiteSnow, 1581 阅读, 2 推荐, 收藏, 编辑
摘要:有段时间没有使用jQuery了,对他的认识还停留在1.2 - 1.4左右。 前几天看,哇,原来jQuery 2.0 beta都发布了…… 以后不敢说自己会jQuery了。 决定趁着年末不忙,干脆分析一下一下其代码吧。 于是,就有了这个系列…… 阅读全文

[置顶]JsCV Core v0.2发布 & Javascript图像处理系列目录

2012-12-28 14:00 by Justany_WhiteSnow, 9329 阅读, 2 推荐, 收藏, 编辑
摘要:JsCV Core是一个开源的Javascript图像处理核心库,其在MIT许可下发布。 阅读全文

Zone.js 简介 & 抛砖引玉

2016-09-12 11:10 by Justany_WhiteSnow, 3496 阅读, 0 推荐, 收藏, 编辑

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

 screenshot

一开始,我对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,则在大型重历史包袱的应用中,可以很好地将多个技术体系共存而不产生恶心的冲突问题。

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

Ques前端组件化体系

2015-07-19 23:56 by Justany_WhiteSnow, 1095 阅读, 0 推荐, 收藏, 编辑
摘要:Ques是一套组件化系统,解决如何定义、嵌套、扩展、使用组件。传统开发模式的痛点无法方便的引用一个组件,需要分别引用其Javascript、Template、CSS文件我们期望能以MV*的方式去写代码,结果发现只有Javascript是MV*UI库打包成一坨(类似Bootstrap),但是实际上UI... 阅读全文

前端测试回顾及我们为什么选择Karma

2015-06-08 00:10 by Justany_WhiteSnow, 5019 阅读, 1 推荐, 收藏, 编辑
摘要:前端测试,或者UI测试一直是业界一大难题。最近Q.js使用Karma作为测试任务管理工具,本文在回顾前端测试方案的同时,也分析下为什么Q.js选用Karma而不是其他测试框架。像素级全站对比曾今有一批人做过这样的UI测试,即最终页面图像是否符合预期,通过图片差异对比来找出可能的问题。如图所示,所谓像... 阅读全文

React直出实现与原理

2015-05-30 22:39 by Justany_WhiteSnow, 15523 阅读, 2 推荐, 收藏, 编辑
摘要:前一篇文章我们介绍了虚拟DOM的实现与原理,这篇文章我们来讲讲React的直出。 比起MVVM,React比较容易实现直出,那么React的直出是如何实现,有什么值得我们学习的呢?为什么MVVM不能做直出?对于MVVM,HTML片段即为配置,而直出后的HTML无法还原配置,所以问题不是MVVM能否直... 阅读全文

HLS视频点播&直播初探

2015-04-26 16:42 by Justany_WhiteSnow, 40994 阅读, 2 推荐, 收藏, 编辑
摘要:前端可选的视频直播协议大致只有两种:RTMP(Real Time Messaging Protocol)HLS(HTTP Live Streaming) 其中RTMP是Adobe开发的协议,无法在iPhone中兼容,故目前兼容最好的就是HLS协议了。HTTP Live Streaming(HLS)是... 阅读全文

前沿技术解密——VirtualDOM

2015-04-08 00:07 by Justany_WhiteSnow, 11969 阅读, 1 推荐, 收藏, 编辑
摘要:作为React的核心技术之一Virtual DOM,一直披着神秘的面纱。实际上,Virtual DOM包含:Javascript DOM模型树(VTree),类似文档节点树(DOM)DOM模型树转节点树方法(VTree -> DOM)两个DOM模型树的差异算法(diff(VTree, VTree) ... 阅读全文

Ques核心思想——CSS Namespace

2015-04-07 00:30 by Justany_WhiteSnow, 754 阅读, 0 推荐, 收藏, 编辑
摘要:Facebook’s challenges are applicable to any very complex websites with many developers. Or any situation where CSS is bundled into multiple files and ... 阅读全文

Unix Pipes to Javascript Pipes

2015-04-07 00:28 by Justany_WhiteSnow, 556 阅读, 0 推荐, 收藏, 编辑
摘要:Unix PipesUnix管道扫描稿简单样例:$ netstat -apn | grep 8080相信这个大家经常使用,这里就不细说了。那么管道基本思想是什么呢?让每个程序只完成一件事,并将其做好(do one thing and do it well),完成一个新任务,新建一个程序,而不是在旧程... 阅读全文

Road to the future——伪MVVM库Q.js

2015-01-28 19:11 by Justany_WhiteSnow, 837 阅读, 1 推荐, 收藏, 编辑
摘要:模仿Vuejs的伪MVVM库,下面是使用说明项目地址:https://github.com/miniflycn/Q.js相关项目:https://github.com/miniflycn/Ques一个简单例子模版:脚本:var vm = new Q({ el: '#demo', data... 阅读全文

聊聊CSS postproccessors

2014-12-05 00:18 by Justany_WhiteSnow, 1683 阅读, 0 推荐, 收藏, 编辑
摘要:阿里妈妈 @一丝 准备发布其CSSGrace,即CSS后处理插件,于是顺便聊聊CSS postprocessors。从Rework说起Rework是TJ大神开发的CSS预处理框架。但为什么会出现呢?TJ大神如此回答:The simple answer is that Rework caters to... 阅读全文
点击右上角即可分享
微信分享提示