缘由

“懒”在软件设计中,有着重大的意义。最常见的两种“懒”,便是:

懒得计算

懒得加载

“懒得计算”常见于服务器端:

比如Multiplayer Online Role-PlayingGame,客户端主动计算,游戏服务器平滑过渡,在性能、游戏同步性找一个合适恰当的点。其目的是节约服务器端CPU、内存等的消耗,把许多消耗性能的计算分布在玩家电脑上;

比如cache,任何cache的目的都是:懒得重新计算,因为我已经计算过了。

比如web应用的表单校验,在数据提交给服务器前进行数据有效性校验,当然这样的目的不是为了省去服务器端的校验,客户端与服务器双校验是必须的,只是过滤一部分正常手段提交错了的格式信息,从而偷一定程度的懒;

“懒得加载”常见于浏览器端:比如图片、视频、音频、css、js等的加载。

拿最常见的焦点图滚动来说:焦点图什么时候初始化完毕?等所有图片加载完成还是第一张图片加载完成?这里可以好好考虑延迟加载。

比如一三屏的网页,用户打开时候处于第一屏?第二屏和第三屏的图片是否要加载?还是根据用户所处的viewport去加载viewport内部的图片?

OK,上面说的都跟本文无关,本文主要讲的是js按需加载。

举个场景

有这样一个页面:

如你所见,用户打开网站,页面有一个a标签,点击可跳转到美女网站,页面还有一个按钮,点击可产生一个运动的小球。如下图所示:

所以专门正对小球抽象出一个对象Ball.js:

define("Ball", {
init: function (x,y,r,vx,vy,text) {
this.x = x;
this.y = y;
this.r = r;
this.d = 2 * r;
this.vx = vx;
this.vy = vy;
this.text = text;
this.element = document.createElement("div");
this.element.innerHTML = text;
this.element.style.cssText = "text-align:center;position:absolute; -moz-border-radius:" + this.d + "px; border-radius: " + this.d + "px; width: " + this.d + "px; height: " + this.d + "px;background-color:green;line-height:" + this.d + "px;color:white;";
document.body.appendChild(this.element);
var self = this;
this.loop = setInterval(function () {
self.tick();
}, 15)
},
tick: function () {
this.x += this.vx;
this.y += this.vy;
this.element.style.left = this.x + "px";
this.element.style.top = this.y + "px";
}
})

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

后来,网站架构师经过随机抽样统计,发现打开这个页面的10000人当中,其中有9999人点击了美女网站直接跳转去看美女了,而仅剩的1人还是个女同胞,打开该页面后立马直接关闭,生怕自己老公发现这块宝地。最后统计的结果就是:那个create a ball 的就根本没有人按过。

既然create a ball从未有人点击,那么这个Ball.js就白白加载了,浪费了用户带宽。

这种场景在各种网站中太多了,比如youku登录相关的弹出层的js,弹出层里表单验证的js。用户进入页面的时候可能仅仅只是想要看视频。所以登录相关的js可以延迟到用户点击登录之后再进行加载和执行。当然这个是js非常小,影响甚微,但是如果某一项目板块特别大粒度,按需加载执行就特别重要。

解决方案

KMDjs作为JS工程化终极解决方案,以Kill AMD和CMD为己任,肯定会提供相关的解决方案。

先说一下,KMDjs的懒执行。这点KMDjs开销真的是太小了,因为大部分逻辑都在init才真正执行,所以KMDjs模块ready的开销仅仅是创建类。

KMDjs又是怎么解决懒加载的呢?不卖关子,直接上码:

var crtBtn = document.getElementById("crtBtn");
var balls = [];
crtBtn.onclick = function () {
kmdjs.get("HelloKMD.Ball", function (Ball) {
var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");
balls.push(ball);
});
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

当然,也支持 promise style:

kmdjs.get("HelloKMD.Ball").then(function (Ball) {
var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");
balls.push(ball);
});

初衷受挫

其实,上面不是我最初想要的lazy方式。我最初想要的是这样的结果:

kmdjs.config({
name:"HelloKMD",
baseUrl: "js",
classes: [
{ name: "HelloKMD.Ball", lazy:true },
{ name: "Util.Bom",url:"Util" }
] });
define("Main",["Util"], {
init: function () { var crtBtn = document.getElementById("crtBtn");
var balls = [];
crtBtn.onclick = function () {
var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");
balls.push(ball);
}
var vp = Bom.getViewport();
setInterval(function () {
for (var i = 0, len = balls.length; i < len; i++) {
var ball = balls[i];
(ball.x + ball.r * 2 > vp[2] || ball.x < 0) && (ball.vx *= -1);
(ball.y + ball.r * 2 > vp[3] || ball.y < 0) && (ball.vy *= -1);
}
}, 100)
}
})

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

可以看到代码没有任何更改,只不过在config里稍微配置了一番,但这几乎要把wind.js集成进来,把

var ball = new Ball(100, 100, 28, 1, 2, "KMD.js");

变成

var ball=$await(new Ball(……..));

而且要去分析ast,还要去分析current scope,还要遍历scope tree,还要去考虑build的问题,还要去…

最终我放弃!选择了这种kmdjs.get的还不错的方式。如果你有更好的想法、建议或意见,请第一时间告诉我,我会将其糅合进0.0.3版本当中。

地址

https://github.com/kmdjs/kmdjs

目前还是0.02版本,kmdjs.get将在0.0.3出现…

AMD and CMD are dead之KMD.js之懒的更多相关文章

  1. AMD and CMD are dead之KMD.js版本0.0.2发布

    更新 正式从UglifyJS切换至UglifyJS2 增加依赖可视化功能 压缩代码更加方便 统一风格:如main的class名也不能省略 优化了kmdjs管道 修复了无数bug 通过src开启debu ...

  2. AMD and CMD are dead之KMD.js依赖可视化工具发布

    使用 require("MyAapp.DepTree", function (DepTree) { DepTree(({ renderTo: "holder", ...

  3. AMD and CMD are dead之KMD规范

    What's KMD? 乱世出英雄,KMD名字的由来充满了杀气. Kill AMD and CMD KMD为替代混乱的AMD和CMD世界而生,一统天下.或者让这个混乱的世界更加混乱,导致: KMD A ...

  4. AMD and CMD are dead之JS工程化终极解决方案KMD.js版本0.0.1发布

    回顾 经过两天晚上疯狂的开发调试,伴随着大量掉落的头发和酸痛的颈椎,KMD.js赢来了第一个稳定版本.在此期间KMD规范也有所修改和完善. 这两天主要完成的功能有: 按需加载 版本控制 模块管理 便捷 ...

  5. AMD and CMD are dead之js模块化黑魔法

    var define, require, define2, require2; typeof JSON != "object" && (JSON = {}), fu ...

  6. AMD and CMD are dead之KMDjs在JS工程化的努力

    总览 kmdjs发布了最接近最终版本的0.0.4版本https://github.com/kmdjs/kmdjs,你已经完全可以在项目中使用.我已经无法用语言形容其完美程度.借用我发的微博:   模块 ...

  7. AMD and CMD are dead之KMDjs集成Blob一键下载全部build包

    更新 不zuo,[A/C]MD就不会死,所以kmdjs赢来来其伟大的版本0.0.6,该版本主要的更新有: 移除去了kmdjs.get(..).then的支持,只支持kmdjs.get(-,functi ...

  8. AMD and CMD are dead之KMDjs内核之依赖分析

    有人说js中有三座大三:this.原型链和scope tree,搞懂了他们就算是js成人礼.当然还有其他不同看法的js成人礼,如熟悉js的:OOP.AP.FP.DOP.AOP.当然还听说一种最牛B的j ...

  9. AMD and CMD are dead之KMDjs内核之分号

    在老版本的kmdjs中,强制了分号的要求.但是总感觉不爽,因为在开发Ket - Kmdjs Extension Tools的时候,总需要导入一些开源的库,然后痛苦就来了,总是报错,一查,就是缺少分号! ...

随机推荐

  1. CTE 递归查询

    使用CTE进行递归查询,能够实现对层次结构的数据的快速访问,非常有用. TSql CTE 递归原理探究 TSql 分层和递归查询 1,CTE的递归结构 递归查询的结构包括两部分:起始点和迭代公式. 使 ...

  2. CSS系列:CSS表格样式

    1. 设置单元格的边框 border-collapse: collapse; 2. 边框的分离 对table使用CSS实现cellspacing的属性border-spacing. border-sp ...

  3. SQL Server 2014新特性探秘(1)-内存数据库

    简介    SQL Server 2014提供了众多激动人心的新功能,但其中我想最让人期待的特性之一就要算内存数据库了.去年我再西雅图参加SQL PASS Summit 2012的开幕式时,微软就宣布 ...

  4. js的作业题

    <script type="text/javascript"> //var a=3; //switch(a) // { // case 1: // alert(&quo ...

  5. 生成Kindle可读的mobi和PDF电子书

    购买kindle之后,自然欣喜万分,不来自于工具本身,而来自于发现自己能够静下心来阅读长篇和复杂的文字了,可喜可贺.更重要的是,kindle减轻了我眼睛的莫大的压力.但马上就出现几个问题: 不是所有的 ...

  6. WebService 学习之路(一):了解并使用webService

    webService主要用于向其他系统提供接口以便调用,系统间可能开发语言等完全不同,根据约定的接口规范,调用者传递相关参数进行接口调用,服务方根据传入的条件进行业务处理并进行结果返回. webSer ...

  7. Notepad++使用小结

    还是那句话“工欲善其事必先利其器”用Notepad++也有一段时间了,也积累了一些东西,写篇博文与大家分享一下使用Notepad++的一些心得.  简单的说一下Notepad++是什么东西吧,Note ...

  8. 史上最详细的iOS之事件的传递和响应机制

    前言: 按照时间顺序,事件的生命周期是这样的: 事件的产生和传递(事件如何从父控件传递到子控件并寻找到最合适的view.寻找最合适的view的底层实现.拦截事件的处理)->找到最合适的view后 ...

  9. 【集合框架】JDK1.8源码分析HashSet && LinkedHashSet(八)

    一.前言 分析完了List的两个主要类之后,我们来分析Set接口下的类,HashSet和LinkedHashSet,其实,在分析完HashMap与LinkedHashMap之后,再来分析HashSet ...

  10. 三步将Node应用部署到Heroku上

    Heroku是一个提供快速部署服务的云平台.支持Node,Ruby,Java,PHP,Python,Go多种语言,今天体验了下,简直不要太爽.下面简单的介绍一下. 首先还是要注册一个账号:https: ...