上一课主要分析了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. POJ 2299 Ultra-QuickSort(线段树入门)

    Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Description In this problem, you have to ana ...

  2. Azure CDN 启用HTTPS

    默认情况下,订阅里的CDN不支持HTTPS 需要联系21v,提交工单告知订阅号,由后台为订阅启用CDN的HTTPS功能. 然后就可以在创建CDN时选到HTTPS的选项了.

  3. linux系统下设置oracle开机自动启动

    在Linux系统中,安装好oracle数据库服务后,并不像在Windows系统下一样,oracle服务在默认情况下会随时系统的启动自动启动.Linux系统中,是需要用户去手动进行设置,才能实现orac ...

  4. 深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

    一.概述   定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的 ...

  5. USACO section1.2 Miking cows

    /* ID: vincent63 LANG: C TASK: milk2 */ #include <stdio.h> #include<stdlib.h> #include&l ...

  6. 边工作边刷题:70天一遍leetcode: day 80

    Palindrome Permutation I/II 要点: oddCount to increase/decrease count II: chars: 先统计,再得到一半的c,相同的在一起,所以 ...

  7. HDU 1085 Holding Bin-Laden Captive --生成函数第一题

    生成函数题. 题意:有币值1,2,5的硬币若干,问你最小的不能组成的币值为多少. 解法:写出生成函数: 然后求每项的系数即可. 因为三种硬币最多1000枚,1*1000+2*1000+5*1000=8 ...

  8. POJ 1845 Sumdiv 【逆元】

    题意:求A^B的所有因子之和 很容易知道,先把分解得到,那么得到,那么 的所有因子和的表达式如下 第一种做法是分治求等比数列的和  用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n: ...

  9. 深入理解maven及应用--转

    (一):生命周期和插件 在项目里用了快一年的maven了,最近突然发现maven项目在eclipse中build时非常慢,因为经常用clean install命令来build项目,也没有管那么多,但最 ...

  10. tomcat7 - 烫手山芋之热部署

    tomcat7部署,项目发布有很多种方式 1. 增量发布,把修改过得那些文件手动上传至tomcat,*.class *.xml 等等,这样的缺点非常大,需要断开tomcat,记住那些你修改过得文件,很 ...