读jQuery之二十(Deferred对象)

Deferred对象是由 jQuery.Deferred 构造的,jQuery.Deferred 被实现为简单工厂模式。

它用来解决JS中的异步编程,它遵循 Common Promise/A 规范。实现此规范的还有 when.js 和 dojo。

 

$.Deferred作为新特性首次出现在版本1.5中,这个版本利用Deferred又完全重写了Ajax模块。

$.Deferred在jQuery代码自身四处被使用,分别是promise方法、DOM ready、Ajax模块、动画模块。

这里以版本1.8.3分析,由于1.7后$.Callbacks从Deferred中抽离出去了,目前版本的deferred.js代码不过150行,而真正$.Deferred的实现只有100行左右。

 

$.extend给标示符$上挂了两个方法,如下

jQuery.extend({Deferred: function( func ) {var tuples = [// action, add listener, listener list, final state[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],[ "notify", "progress", jQuery.Callbacks("memory") ]],...// All done!return deferred;},// Deferred helperwhen: function( subordinate /* , ..., subordinateN */ ) {var i = 0,resolveValues = core_slice.call( arguments ),length = resolveValues.length,....return deferred.promise();}
});

 

$.Deferred的实现

  1. 创建三个$.Callbacks对象,分别表示成功,失败,处理中三种状态
  2. 创建了一个promise对象,具有state、always、then、primise方法
  3. 通过扩展primise对象生成最终的Deferred对象,返回该对象

 

$.when的实现

  1. 接受若干个对象,参数仅一个且非Deferred对象将立即执行回调函数
  2. Deferred对象和非Deferred对象混杂时,对于非Deferred对象remaining减1
  3. Deferred对象总数 = 内部构建的Deferred对象 + 所传参数中包含的Deferred对象
  4. 所传参数中所有Deferred对象每当resolve时remaining减1,直到为0时(所有都resolve)执行回调

 

这就是$.Deferred和$.when的全部了,各个方法及使用稍后介绍。

代码阅读中会发现then和when方法的实现最难理解,看多次,后感回味无穷,非常巧妙。then内部会用到不同寻常的递归,when用到了计数,每次异步成功后减一,直到为0后表示全部异步操作成功,这时才可执行回调。

 

上面提到Deferred里有3个$.Callbacks的实例,Deferred自身则围绕这三个对象进行更高层次的抽象。以下是Deferred对象的核心方法

  • done/fail/progress 是 callbacks.add,将回调函数存入
  • resolve/reject/notify 是 callbacks.fire,执行回调函数(或队列)

 

下面举一些示例看看如何使用Deferred对象。

 

一、done/resolve

function cb() {alert('success')
}
var deferred = $.Deferred()
deferred.done(cb)
setTimeout(function() {deferred.resolve()
}, 3000)

在HTTP中表示后台返回成功状态(如200)时使用,即请求成功后可执行成功回调函数。

 

二、fail/reject

function cb() {alert('fail')
}
var deferred = $.Deferred()
deferred.fail(cb)
setTimeout(function() {deferred.reject()
}, 3000)

在HTTP中表示后台返回非成功状态时使用,即请求失败后可执行失败回调函数。

 

三、progress/notify

function cb() {alert('progress')
}
var deferred = $.Deferred()
deferred.progress(cb)
setInterval(function() {deferred.notify()
}, 2000)

在HTTP中表示请求过程中使用,即请求过程中不断执行回调函数。这可用在文件上传时的loading百分比或进度条。

 

四、链式操作

function fn1() {alert('success')
}
function fn2() {alert('fail')
}
function fn3() {alert('progress')
}
var deferred = $.Deferred()
deferred.done(fn1).fail(fn2).progress(fn3) // 链式操作
setTimeout(function() {deferred.resolve()//deferred.reject()//deferred.notify()
}, 3000)

这样可以很方便了添加成功,失败,进度回调函数。

 

五,便利函数then,一次添加成功,失败,进度回调函数

function fn1() {alert('success')
}
function fn2() {alert('fail')
}
function fn3() {alert('progress')
}
var deferred = $.Deferred()
deferred.then(fn1, fn2, fn3)

调用then后还可以继续链式调用then添加多个不同回调函数,这个then也正是jQuery对 Common Promise/A 的实现。

 

六、使用always方法为成功,失败状态添加同一个回调函数

var deferred = $.Deferred()
deferred.always(function() {var state = deferred.state() if ( state === 'resolved') {alert('success')} else if (state === 'rejected') {alert('fail')}
})
setTimeout(function() {deferred.resolve()//deferred.reject()
}, 3000)

回调函数中可以使用deferred.state方法获取异步过程中的最终状态,这里我调用的是deferred.resolve,因此最后的状态是resolved,表示成功。

 

七、when方法保证多个异步操作全部成功后才回调

function fn1() {alert('done1')
}
function fn2() {alert('done2')
}
function fn3() {alert('all done')
}var deferred1 = $.Deferred()
var deferred2 = $.Deferred()deferred1.done(fn1)
deferred2.done(fn2)
$.when(deferred1, deferred2).done(fn3)setTimeout(function() {deferred1.resolve()deferred2.resolve()
}, 3000)

先后弹出了done1、done2、all done。 如果setTimeout中有一个reject了,fn3将不会被执行。

 

八、deferred.promise()方法返回只能添加回调的对象,这个对象与$.Deferred()返回的对象不同,只能done/fail/progress,不能resolve/reject/notify。即只能调用callbacks.add,没有callbacks.fire。它是正统Deferred对象的阉割版。

 

 

有了Deferred,我们使用jQuery书写ajax的风格可以这样了

$.ajax(url).done(success).progress(handling).fail(fail)

 

看似和以前比较也没什么优点,但它还可以添加多个回调

$.ajax(url).done(success1).done(success2).fail(fail2).fail(fail2)

1.5之前的则不行

 

如果多个请求完成后才算成功,1.5之前的是无法解决的,现在则可以用$.when搞定

var ajax1 = $.ajax(url1)
var ajax2 = $.ajax(url2)
$.when(ajax1, ajax2).done(success)

 

如果项目中有一些异步问题不妨用用Derferred。

 

相关:

http://jimliu.net/?p=64

http://www.infoq.com/cn/news/2011/09/js-promise

http://www.erichynds.com/jquery/using-deferreds-in-jquery/

http://sitr.us/2012/07/31/promise-pipelines-in-javascript.html

http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301857.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET之盛派微信SDK简单操作

开篇语在6月5号,我报名去参加了微软举办的一个线下分享的技术市集,分享人是苏老师和赵老师(非常感谢),其中苏老师讲述了关于一些容器的部署等操作(也可以观看我的历史文章),其中关于部署的示例代码是使用盛派微信SDK做了一个对接微…

预售┃连锁反应装置积木好玩到尖叫!

▲数据汪特别推荐点击上图进入玩酷屋之前推荐的“小小机械师”成了孩子最受欢迎的玩具,玩了的孩子几乎没有不喜欢的。还有家长买多套送给朋友的孩子作为生日礼物。有家长来问,还有没有这种类型的新产品。和厂家咨询后,小木找到了一款“小小机…

java文件调用脚本_Java中调用文件中所有bat脚本

//调用外部脚本String fileipsnull;//所有的路径String[] filesnull;String fileipnull;//单个路径try {InputStream is Thread.currentThread().getContextClassLoader().getResourceAsStream("pdfconfig.properties"); //加载线程文件成为流Properties prop new …

VMware VSphere 虚拟化云计算学习配置笔记(四)

2:接下来配置安装vcenter-db,安装MS SQL 2008r2 在vcenter-db服务器上安装配置MS SQL 2008r2过程截图: 这里可能会要耐心等一下才会出现一下提示: 选择左边installation 之后出现右边第一项新的安装: 转载于:https://blog.51cto.c…

【招聘(北京)】今天誉讯(北京)有限公司招聘高级.NET软件开发前端工程师

.NET高级开发工程师薪水范围:18-25k工作职责1、负责公共平台开发与维护,根据网站发展对技术架构不断调整、对网站性能调优;2、完成详细需求的分析与设计,并完成相关技术文档;3、按照项目任务和项目计划,完成…

IT人回家过年的尴尬

全世界只有3.14 % 的人关注了数据与算法之美春节将至,有很多人已经踏上了返乡的旅途,回家开开心心过春节,归心似箭的心表明了他们对家乡的热爱,归心似箭的心显示了他们想念父母的情,归心似箭的心代表了他们对朋友的思。…

java 判断进程状态_获取远程服务器上 Java 进程的运行状态

为了安全考虑, 有些服务器会被限制登录. 本文介绍如何获取远程服务器上 Java 进程的运行状态.启动 jstatd 服务在服务器端启动 jstatd 服务后, 远程的机器可以通过 rmi 协议获取服务器上 Java 程序的运行状态.在服务器上创建 jstatd 的授权文件, 假设文件路径为/etc/jstatd.all…

彻底搞定C指针-函数名与函数指针[转]

一 通常的函数调用 一个通常的函数调用的例子: //自行包含头文件 void MyFun(int x); //此处的申明也可写成:void MyFun( int );int main(int argc, char* argv[]) {MyFun(10); //这里是调用MyFun(10);函数return 0; }void MyFun(int x) //这…

聊一聊Elasticsearch和MySQL的常用操作

前言 ElasticSearch,开源的搜索和数据分析引擎,也是名列前茅的 nosql。很多时候会想拿它和关系型数据库做对比,严格上它们是没有太多可比性的。不过把有的东西放在一起比较,会帮助我们快速去理解一些 ElasticSearch 的内容。老黄这…

入门Python,限时1元!

爆竹声中一岁除,春风送暖入屠苏。猪年来袭,小天先跟各位模粉拜年啦!当然,小天还准备了限时福利送给大家~套路?不存在的!限时9元1深度学习限时体验第一章 深度学习概述与计算机视觉挑战1.1深度学习概述1.2 挑…

java 线程访问控件_C#多线程与跨线程访问界面控件的方法

本文实例讲述了C#多线程与跨线程访问界面控件的方法。分享给大家供大家参考。具体分析如下:在编写WinForm访问WebService时,常会遇到因为网络延迟造成界面卡死的现象。启用新线程去访问WebService是一个可行的方法。典型的,有下面的启动新线程…

centos服务器解决vsftp连接时的“550 Create directory operation failed.”错误

在centos服务器中配置好vsftp后,开了root用户上传权限,也关了系统的防火墙,但ftp连接的时候依然还会出现 "550 Create directory operation failed." 错误,如何解决呢? 解决: 1、查看 SELinux 的…

使用 Bridge to Kubernetes 简化云端开发

当我们面对一个大型应用程序,它有大量的微服务,并希望完成一些功能开发?我们面临许多挑战,其中之一将是处理正确的环境,如何进行开发。我们知道,在团队中解决这个问题的最佳方法是将其容器化并在云上托管。…

菜鸟学习数据科学家 5 大误区

全世界只有3.14 % 的人关注了数据与算法之美你准备好要成为一名数据科学家,积极的参加Kaggle比赛和Coursera的讲座。虽然这一切都准备好了,但是一名数据科学家的实际工作与你所期望的却是大相径庭的。本文研究了作为数据科学家新手的5个常见错误。这是由…

java多线程 sycophantic_Java多线程volatile和synchronized总结

volatile是轻量级的synchronized,在多处理器(多线程)开发中保证了共享变量的“可见性”。可见性表示当一个线程修改了一个共享变量时,另外一个线程能读到这个修改的值。正确的使用volatile,能比synchronized的使用和执行成本更低,…

[BOOST] BOOST::Format

cout << format( "%1% says \"%2%\" to %1%.\n" ) % "Yousen" % "Hello";这句话将在标准输出上输出“Yousen says "Hello" to Yousen.”接下来简单说明一下format的用法。估计聪明人都猜到了&#xff0c;在格式化字符…

using IDisposable

using和IDisposable是组合使用的&#xff0c;像这种一个关键字和一个接口的组合&#xff0c;在C#中很少见的&#xff0c;using这个关键字&#xff0c;也就因为IDisposable多了一个身份。其实很多人都知道IDisposable&#xff0c;有一个方法void Dispose()&#xff0c;通常是用来…

春节特惠活动┃不只是舒适,简直是享受,Google公司用的腰靠,到底有什么秘密?...

▲数据汪特别推荐点击上图进入玩酷屋之前小木推荐“德国MINICUTE人体工学腰垫”受到了大家一致的好评和争相购买。小木为什么推荐这一款原因是&#xff1a;据统计&#xff0c;我国腰椎病患者已经突破2亿人。30~40岁人群中&#xff0c;患有颈腰椎病的占比59.1%&#xff01;而且有…

linux mysql phpadmin_linux安装phpmyadmin数据库管理

安装phpmyadminyum -y install phpmyadmin //执行yum在线安装程序安装完成后&#xff0c;可在/usr/share目录下找到phpMyAdmin找到 phpMyAdmin/libraries/config.default.php文件&#xff0c;将config.default.php复制到phpmyadmin目录下&#xff0c;然后更名为config.inc.…

2012平安夜

2012平安夜&#xff0c;我的博客园开通了&#xff0c;在这里我将与他开始崭新的学习生活。