Deferred对象是由$.Deferred构造的,$.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行左右。
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 helper when: function( subordinate /* , ..., subordinateN */ ) { var i = 0, resolveValues = core_slice.call( arguments ), length = resolveValues.length, .... return deferred.promise(); } });
$.Deferred的实现
- 创建三个$.Callbacks对象,分别表示成功,失败,处理中三种状态
- 创建了一个promise对象,具有state、always、then、primise方法
- 通过扩展primise对象生成最终的Deferred对象,返回该对象
$.when的实现
- 接受若干个对象,参数仅一个且非Deferred对象将立即执行回调函数
- Deferred对象和非Deferred对象混杂时,对于非Deferred对象remaining减1
- Deferred对象总数 = 内部构建的Deferred对象 + 所传参数中包含的Deferred对象
- 所传参数中所有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) .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://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
相关推荐
jquery基础教程之deferred对象使用方法
Promises是一种令代码异步行为更加优雅的抽象,它很有可能是JavaScript的下一个编程范式,一个Promise即表示任务结果,无论该...本文以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题,需要的朋友参考下
主要介绍了jQuery之Deferred对象详解,本文深入剖析了jQuery Deferred对象的方法属性等内容,需要的朋友可以参考下
主要介绍了jQuery通过deferred对象管理ajax异步的相关资料,需要的朋友可以参考下
在jquery1.5之后的版本中,加入了一个deferred对象,也就是延迟对象,用来处理未来某一时间点发生的回调函数。同时,还改写了ajax方法,现在的ajax方法返回的是一个deferred对象。 那就来看看deferred对象的用法。 1...
deferred对象是jQuery的回调函数解决方案,它是从jQuery1.5.0版本开始引入的功能 deferred对象的方法 (1) $.Deferred() 生成一个deferred对象。 (2) deferred.done() 指定操作成功时的回调函数 (3) deferred....
本文实例讲述了javascript异步处理与Jquery deferred对象用法。分享给大家供大家参考,具体如下: 这是项目组老大整理的一些关于jquery 异步处理请求,以及使用 jquery deferred 对象的一些常见方法。虽然是项目上...
主要介绍了jQuery的promise与deferred对象在异步回调中的作用,需要的朋友可以参考下
前段时间看了阮一峰的jQuery的deferred对象详解一文,对jQuery中的deferred的用法了一些了解,今天看到园子里的一篇文章:关于重构JS前端框架的失败经验(顺便怀念那些死去的代码),于是把我之前写的一个利用jQuery...
一个Deferred.Promise对象可以理解为是deferred对象的一个视图,它只包含deferred对象的一组方法,包括:done(),then(),fail(),isResolved(), isRejected(), always(),这些方法只能观察一个deferred的状态,而无法...
HTML+CSS3+JS+JQuery实现七夕言情动画、面向对象程序设计、Deferred对象解决异步编程回调嵌套问题
为了改变这一点,jQuery开发团队就设计了deferred对象。 简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是”延迟”,所以deferred对象的含义就是”延迟”到未来某个
deferred对象是jQuery对Promises接口的实现。接下来通过本文给大家详解介绍jQuery中的deferred对象的使用(一),需要的朋友一起学习吧
译者注:1. Deferred是jQuery1.5...jQuery1.5中新增的Deferreds对象,可以将任务完成的处理方式与任务本身解耦合。这在JavaScript社区没什么新意,因为Mochikit和Dojo两个JS框架已经实现了这个特性很长一段时间了。
主要介绍了谈谈jQuery之Deferred源码剖析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧