上一课主要分析了jQuery1.51版本的jQuery Deferred。在jQuery1.6中,jQuery Deferred添加了两个方法,always,pipe。

always用来添加回调,无论成功还是失败,都会执行。

pipe就是管道的意思,对回调使用瀑布模型,上一个回调的返回值供下一个会调使用。

我们举个例子来说明下pipe与then的区别:

var deferred = $.Deferred();  //返回的是Deferred对象

var promise = deferred.pipe(function(a){return a*2}).pipe(function(a){return a*4;})   //pipe方法的返回值是Promise对象,因此promise与deferred不相等。

deferred.resolve(5);     //执行这个函数后,就会调用pipe添加进来的回调函数。第一个回调函数中的a=5,然后返回10给第二个回调函数,因此第二个回调中的a=10。

$.Deferred().then(function(a){return a*2;}).then(function(a){return a*4;}).resolve(5);

第一个回调函数中的a=5,第二个回调函数中的a=10,跟pipe方法一样。它们的区别是then方法返回的是Deferred对象,因而可以进行链式操作,而pipe方法返回的是Promise对象,不能进行链式操作。

在这个版本的jQuery中,Deferred开始在jQuery内部大规模应用了,包括queue模块,Ajax模块。

举个很好的例子:

var stuff1 = function(deferred){

  setTimeout(function(){deferred.resolve()},1000);

};

var stuff2 = function(deferred){

  setTimeout(function(){deferred.resolve()},500);

};

var stuff3 = function(deferred){

  setTimeout(function(){deferred.resolve()},800);

};

var stuff4 = function(deferred){

  setTimeout(function(){deferred.resolve()},800);

};

$.when(    //此方法接受了三个Deferred对象,只有等这三个Deferred对象的状态结束后(也就是执行了各自的resolve方法后),才会执行then添加的回调方法。

  $.Deferred(stuff1),   //此方法会执行stuff1方法,并且把新创建的Deferred对象传进去,返回此Deferred对象,1秒后,调用此Deferred对象的resolve方法。

  $.Deferred(stuff2),   //同上,只是异步处理的时间不一样。

  $.Deferred(stuff3)    //同上,这里的setTimeout的异步处理,我们可以当做是ajax请求的时间长度。

).then(stuff4);   //给$.when()方法返回的Deferred对象添加回调函数stuff4。等when方法中传入的所有Deferred对象的状态结束后,就会执行此回调stuff4.

这段代码的理解你可以当做是:有三个ajax请求,请求的地址不一样,我们需要等这三个ajax请求都返回后,把这三个请求回来的数据进行整合处理,才能进行最后一个ajax请求。

jQuery1.7添加了Callbacks模块,具体可以看:http://www.cnblogs.com/chaojidan/p/4165818.html。

而且也改写了Deferred模块。这个时候的Deferred,它是一个三链结构(doneList,failList,progressList)。progressList链添加了三个API,progress,notify,notifyWith,用来给此链添加回调和触发回调。progressList链是用来干嘛的?我们知道成功队列doneList与失败队列failList都是一次性的,也就是说触发了一次就不能再触发了。但是有时,我们需要反复触发,那么就可以用progressList来解决。

举个例子:

var a = $.Deferred();

a.done(function(x){console.log(x);}).done(function(x){console.log(x)});

a.resolve(1);

如果大家看了上一课的jQuery Deferred的源码,就知道,创建了一个新的延迟对象a,然后通过done方法添加了两个成功回调函数,最后通过resolve方法触发a的成功回调,因此会执行这两个成功回调函数,打印出两个1.

这时如果你再调用a.resolve(2);再次触发a的成功回调,不会打印出两个1.

但是progressList可以,

var b = $.Deferred();

b.progress(function(x){console.log(x);}).progress(function(x){console.log(x)});

b.notify(1);

b.notify(2);

第一个notify会打印出两个1,第二个notify会打印出两个2.

从上面的例子中,大家可以看出,doneList,failList触发一次状态后,就会结束了,你后面再次触发同样的状态,是不会执行回调函数的。但是progressList可以触发多次状态,也就意味着你只要调用notify,就会执行progress添加的回调函数。

jQuery1.8又对Deferred进行了重构,不过思路是一致的。

Promise/A隶属于Promise规范,而Promise规范则又隶属于CommonJS。

Promise/A规范大概是这样描述的:一个带有then方法的对象,它拥有3个状态,fulfilled,rejected,pending。then方法可以传入三个函数,一个是成功时执行的回调函数onFulfill,一个是失败时执行的回调函数onReject,一个是进行中执行的回调函数onNotify,它不会改变对象的状态(刚开始对象就处于pending,当执行成功回调函数onFulfill后,对象就会变成fulfilled状态,当执行失败回调函数onReject后,对象就会变成rejected状态,当执行进行中回调函数onNotify后,对象状态不会改变,还是pending状态)。这三个函数都是可选的,如果是非函数,就忽略掉。then方法会返回一个新的Promise对象,以便能够实现链式操作。

后来人们在Promise/A的规范上添加了更多的细节,形成了Promise/A+规范。现在市面上有三大Promise/A+库,分别是:Q,RSVP,when。其中,Q的微缩版被整进angular.js,RSVP被整进了ember.js。这两个库就是著名的MVVM库。后面的章节将会讲到这两个库,我也很期待。

js异步处理的前景

未来的javascript将支持yield生成器(generator),目前只有Firefox浏览器有,但是需要自己打开实验性开关。

<script type="text/javascript; version=1.7">    //这里改成1.8也行

  //这里面就可以使用yield了

</script>

此yield,可以让我们轻松的以同步的形式写出异步的代码。你只需要将它们放到某个函数体内。相应的库有:taskjs,gens,tamejs等。

有人对各种不同实现的异步库进行性能评测,基于原生生成器的库总体上占优势。yield语句比回调更能及时的工作,耗时更少。

但是在目前,实现生成器的代码量非常大,而实现Promise则相对轻松一些,因此Promise是当下最廉价的异步方案。

yield还没有真正的发展起来,因此不用精读。知道有这么一个东西就行。

下一课,将讲解Ajax,大家可以先去看一下Ajax Hacks这本书。

加油!

第三十四课:jQuery Deferred详解2的更多相关文章

  1. 第三十五课:Ajax详解

    一个完整的Ajax请求: var xhr = new (self.XMLHttpRequest || ActiveXObject)("Microsoft.XMLHTTP");   ...

  2. 第三十九课:requestAnimationFrame详解

    大家应该都知道,如果一个页面运行的定时器很多,无论你怎么优化,最后肯定会超过指定时间才能完成动画.定时器越多,延时越严重. 为此,YUI,kissy等采用中央队列的方式,将定时器减少至一个.浏览器厂商 ...

  3. NeHe OpenGL教程 第三十四课:地形

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. “全栈2019”Java第五十四章:多态详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. 第三十三课:jQuery Deferred详解1

    之前我们讲了Mochikit Deferred,JSDeferred,现在讲jQuery Deferred.首先,我们先来讲下他们的区别: 在保存回调函数时,Mochikit Deferred(doj ...

  6. Jquery Deferred 详解

    近期由于公司项目主要由我来负责前端,所以打算优化一下代码.在jquery 里面有个Deferred的对象.为了研究这个也看了不少资料,其中阮一峰的博客写的很详细,这里转载一下. 一.什么是deferr ...

  7. JAVA学习第三十四课 (经常使用对象API)—List集合及其子类特点

    整个集合框架中最经常使用的就是List(列表)和Set(集) 一.List集合 && Set的特点 Collection的子接口: 1.List:有序(存入和取出的顺序一致),元素都有 ...

  8. 潭州课堂25班:Ph201805201 django 项目 第三十四课 后台文章标签更新功能 ,创建功能实现(课堂笔记)

    g更改标签:,前台要向后台传来 id, name, 对标签进行校验:标签不能为空,标签是否已经存在, 流程: def put(self, request, tag_id): ''' 更改标签 :par ...

  9. python第三十四课——2.匿名函数配合容器函数的使用

    匿名函数配合容器函数的使用(了解) 1.匿名函数配合列表对象使用 lt=[lambda x:x**2,lambda x:x**3,lambda x:x**4] for i in lt: print(i ...

随机推荐

  1. 数据结构--线段树--lazy延迟操作

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 53749   ...

  2. Linux学习之六——使用vi和vim

    一.vi的三种模式和相互切换 1. 一般模式 1) 移动光标 可以用箭头键,Page Up, Page Down, Home,End等按键移动光标 G,移动到档案最后一行 1G,gg,移动到档案第一行 ...

  3. Js脚本选取iframe中的元素

    遇到个小问题,需要用到原生Js处理页面中的元素,以往一个document.getElementById就完活的选取元素,这次却不好使了.. 仔细看代码发现要选取元素外面多了一个iframe标签 < ...

  4. Linux shell misc

    sometimes you will write shell in windows platform, be careful for this, adjust the notepad plus plu ...

  5. struts2 基本用法

    Struts2必需库: commons-fileupload.jar.commons-io-1.3.2.jar.freemarker-2.3.16.jar.javassist-3.7.ga.jar.o ...

  6. [转]Excel - How to lock cell without using macros if possible

    本文转自:http://stackoverflow.com/questions/11953214/excel-how-to-lock-cell-without-using-macros-if-poss ...

  7. java常用方法总结

    最近打算换工作,还是需要补一下面试的基础知识,写了一些面试中可能会用到的常用算法.方法,以便复习 //99乘法表 /** * 1*1 * 1*1 1*2 * 1*1 1*2 1*3 * …… * */ ...

  8. 【温故而知新-Javascript】窗口效果 (全屏显示窗口、定时关闭窗口)

    1.全屏显示窗口 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...

  9. unity3D里面的点乘和叉乘

    在unity3D里面.两个向量的点乘所得到的是两个向量的余弦值,也就是-1 到1之间,0表示垂直,-1表示相反,1表示相同方向. 两个向量的叉乘所得到的是两个向量所组成的面的垂直向量,分两个方向. 简 ...

  10. Java Executor并发框架(一)整体介绍

    一.概述 Java是天生就支持并发的语言,支持并发意味着多线程,线程的频繁创建在高并发及大数据量是非常消耗资源的,因为java提供了线程池.在jdk1.5以前的版本中,线程池的使用是及其简陋的,但是在 ...