JSDeferred 源码分析
不经意看到了一个构思非常惊人的异步流程控制库,发出来分享下
http://cho45.stfuawsc.com/jsdeferred/
关于CommonJS Promises请看另一个异步库 http://www.cnblogs.com/aaronjs/p/3168588.html
整个代码非常简洁,易用,不过呢是小日本写的东西…
API手册:
加载jsdeferred定义延迟对象。为方便起见,我们用Deferred.define()方法把接口导出到全局作用于中
Deferred.define();
通过这样做,你就能使用如 next(), loop(), call(), parallel() and wait() 这样的全局函数方法,让我们抒写一些异步的流程
next(function () {
alert("Hello!");
return wait(5);
}).
next(function () {
alert("World!");
});
这个流程中,开始会弹出 “Hello”,然后过5秒接着会弹出 “world”
Deferred.next(function () {
alert("Hello!");
return Deferred.wait(5);
}).
next(function () {
alert("World!");
});
上面是抒写同上
个人分析:
用Deferred.define()方法,无疑污染了全局作用域,入侵性太强了,跟mootools,prototype一样, 不过好处嘛,很明显,简单易用了
还好JSDeferred也提供了无侵入的写法
亮源码:
Deferred.define = function (obj, list) {
if (!list) list = Deferred.methods;
if (!obj) obj = (function getGlobal() {
return this
})();
for (var i = 0; i < list.length; i++) {
var n = list[i];
obj[n] = Deferred[n];
}
return Deferred;
};
可以传入一个对象,用作上下文
var o = {}; //定义一个对象
Deferred.define(o);//把Deferred的方法加持到它上面,让o成为一个Deferred子类。
o.next(function(){
/* 处理 */
})
Deferred.methods = ["parallel", "wait", "next", "call", "loop", "repeat", "chain"];
next方法
- next方法是可以进行链式操作,链式的原理很简单就是要返回当前的的this上下文才可以
- 所以很明显第一个next我们必须要建一个上下文对象提供给后面next引用,其实跟jquery链式一个道理
根据源码看来Deferred.next其实就是一个静态方法
Deferred.next = Deferred.next_faster_way_readystatechange
|| Deferred.next_faster_way_Image
|| Deferred.next_tick
|| Deferred.next_default;
显而易见,next方法是有四种选择优先级,为什么要这样呢?
- 目的是用于提供了一个JSDeferred实例与实现第一个异步操作。
- 异步操作在JSDeferred中有许多实现方法,如setTimeout,img.onerror或 script.onreadystatechange ,
- 它会视浏览器选择最快的异步方式
我是基于webkit的游览器,所以我们就直接看Deferred.next_faster_way_Image
// Modern Browsers
var d = new Deferred();
var img = new Image();
var handler = function () {
d.canceller();
d.call();
};
img.addEventListener("load", handler, false);
img.addEventListener("error", handler, false);
d.canceller = function () {
img.removeEventListener("load", handler, false);
img.removeEventListener("error", handler, false);
};
img.src = "data:image/png," + Math.random();
if (fun) d.callback.ok = fun;
return d;
流程:
- 创建一个Deferred对象
- 创建Image对象,实现异步
- 监听事件
- if (fun) d.callback.ok = fun; 放置回调处理对象
- 返回当前deferred对象
由此可见
next(fn).next(fn).next(fn)
其实就是
第一个 next() Deferred.next_faster_way_Image () 返回 d 第二个 next() d.next()
第二个next(),其实就是实例Deferred类的原型方法了
具体我们看
next: function (fun) {
return this._post("ok", fun)
},
_post: function (okng, fun) {
this._next = new Deferred();
this._next.callback[okng] = fun;
return this._next;
},
看到_post方法,就有拨开云雾见月明的感觉了
其实内部会有重新生成一个 Deferred对象挂到父实例的 next上,在绑定回调..
如此依次循环处理
所以初始化的时候其实内部就生成了这么一个队列

_next 上都挂着下一个队列处理
此时都是在初始化准备好的了,在执行的时候 Image 在成功回调中,我们调用了 d.call();
执行实例的call方法
call: function (val) {
return this._fire("ok", val)
},
_fire: function (okng, value) {
var next = "ok";
try {
value = this.callback[okng].call(this, value);
} catch (e) {
next = "ng";
value = e;
if (Deferred.onerror) Deferred.onerror(e);
}
if (Deferred.isDeferred(value)) {
value._next = this._next;
} else {
if (this._next) this._next._fire(next, value);
}
return this;
}
- 取出当前实例的回调方法,传入参数
- 返回的value 是否还是一个isDeferred对象
- 如果没有返回值,继续调用内部的_next上的Deferred实例,依次循环
总结:
构思很特别,把每次链式的回调挂到内部的next子属性中,在处理上也保持了一条线的引用关系,而不是常规的用数组的方式存起来
当然上面仅仅只是同步方法的处理分析,也不是标准的遵循CommonJS Promises规范去抒写的
JSDeferred 源码分析的更多相关文章
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
- zookeeper源码分析之四服务端(单机)处理请求流程
上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...
- ABP源码分析二:ABP中配置的注册和初始化
一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...
- ABP源码分析三:ABP Module
Abp是一种基于模块化设计的思想构建的.开发人员可以将自定义的功能以模块(module)的形式集成到ABP中.具体的功能都可以设计成一个单独的Module.Abp底层框架提供便捷的方法集成每个Modu ...
随机推荐
- Python微信-- 分享接口(分享到朋友圈、朋友、空间)
生成JS-SDK权限验证的签名 获取signature(签名)首先要获得 1.#获得jsapi_ticket 2.#获取当前页面的url #获取当前页面的url url="{}://{}{} ...
- asp.net,cookie,写cookie,取cookie
Cookie是一段文本信息,在客户端存储 Cookie 是 ASP.NET 的会话状态将请求与会话关联的方法之一.Cookie 也可以直接用于在请求之间保持数据,但数据随后将存储在客户端并随每个请求一 ...
- git flow工作流实际项目实践
公司项目的开发流程主要是这样 代码分为 develop分支 master分支 平时我开发的时候,主要在develop分支上改动 一般来讲,有以下几种改动方式 1.直接在develop上修改代码 这种一 ...
- 【PostgreSQL】PostgreSQL添加新服务器连接时,报错“Server doesn't listen ”,已解决。
PostgreSQL添加新的服务器连接时,报错:
- C#委托与事件初探
最近刚刚接触C#,学到事件与委托部分无法理解,于是上网查阅了各种资料,终于明白了一些,在此进行总结. 一.C语言中的函数指针 想要理解什么是委托,就要先理解函数指针的概念.所谓函数指针,就是指向函数的 ...
- 站内全文检索服务来了,Xungle提供免费全文检索服务
免费站内全文检索服务来了,是的,你没听错.全文检索相信大家已经不太陌生,主流检索服务有sphinx.xunsearch等,但这些都受服务器限制,对于中小站长尤其是没有服务器实现就困难了,随着数据量的增 ...
- 机器学习&深度学习资料
机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1) 机器学习(Machine Learning)&深度学习(Deep Lea ...
- elasticsearch 之mapping
搭好elk 后,有时候会发现kibana 统计数据时,数据类型不对,这个时候就和elasticsearch的mapping有关,虽然我们可以用logstash修改传入es里的数据类型,比如 float ...
- 导入导出Excel工具类ExcelUtil
前言 前段时间做的分布式集成平台项目中,许多模块都用到了导入导出Excel的功能,于是决定封装一个ExcelUtil类,专门用来处理Excel的导入和导出 本项目的持久化层用的是JPA(底层用hibe ...
- Visual 2015创建新项,缺少ADO.NET 实体数据模型的解决方法
现在的某度查资料真的很麻烦,突然我自身的VS2015创建EF的时候找不到 ADO.NET 实体数据模型,但是使用CodeFrist是可以生成数据表的.所有特别郁闷. 打开界面如下 某度半天,都没有查出 ...