jQuery.deferred详解
deferred是什么?
deferred 翻译为推迟,在jQuery 1.5中引入的Deferred对象是通过调用jQuery.Deferred()方法创建的可链接实用程序对象。它可以在回调队列中注册多个回调函数,调用回调队列,并中继任何同步或异步函数的成功或失败状态。
deferred能为我们解决什么问题?
我们常常会遇到这种问题,
定义一个变量, 在a函数中为它赋值 ,在b函数中调用它 。
如下场景:
var current = 0;
function a() {
setTimeout(function () {
current = 6;
}, 500);
}
function b() {
a();
console.log(current);
}
b(); // 0
b函数没有等待a函数赋值成功便执行了,导致console出的值是current 的初始值。
为了解决这个问题,我们肯定想到回调。
var current = 0;
function a(callback) {
setTimeout(function () {
current = 6;
callback();
}, 500);
}
function b() {
a(function(){
console.log(current);
});
}
b(); // 0
通过回调函数,b函数得到了赋值6。
那么有更多的函数在b函数之前对current 赋值,那么....
function b() {
a(function(){
c(function(){
d(function(){
console.log(current);
})
})
});
}
上面的情况让我们的代码变的复杂、可读性很差。
而deferred对象的产生是为jQuery回调函数提供解决方案。
$.when(a, c, d)
.then(b);
这样既简化了代码,可读性也增强了很多。_
jQuery deferred使用方法及使用场景?
Deferred对象是可链接的,类似于jQuery对象是可链接的,但它有自己的方法。创建Deferred对象后,可以使用以下任何方法,直接从对象创建链接或将对象保存在变量中再调用该变量创建一个或多个方法。
deferred.always()
当Deferred对象被resolved或rejected时,将会调用的函数。
deferred.catch()
当Deferred对象被rejected时,将会调用的函数。
deferred.done()
当Deferred对象被resolved时,将会调用的函数。
deferred.fail()
当Deferred对象被rejected时,将会调用的函数。
deferred.isRejected()
测定Deferred对象是否已被rejected。
deferred.isResolved()
测定Deferred对象是否已被resolved。
deferred.notify()
根据给定的 args参数 调用Deferred对象上进行中的回调
deferred.notifyWith()
根据给定的文本和args参数 调用Deferred对象上进行中的回调
deferred.pipe()
用用于过滤 and/or 链式Deferred对象的工具方法。
deferred.progress()
当Deferred对象生成正在执行中的进度通知时, 将会调用的函数。
deferred.promise()
返回Deferred Promise对象。
deferred.reject()
根据给定的 args参数 Reject Deferred对象并调用所有失败回调函数。
deferred.rejectWith()
根据给定的文本和args参数 Reject Deferred对象并调用所有失败回调函数。
deferred.resolve()
根据给定的 args参数 Resolve Deferred对象并调用所有成功回调函数。
deferred.resolveWith()
根据给定的文本和args参数 Resolve Deferred对象并调用所有成功回调函数。
deferred.state()
测定Deferred对象的当前状态。
deferred.then()
当Deferred对象被rejected、resolve、正在进行中时,将会调用的函数。
jQuery.when()
为一种基于零个或多个对象(通常为表示异步事件的Deferred对象)提供执行回调函数的方法。
.promise()
返回一个Promise对象以观察绑定到集合的某个类型的所有操作何时完成。
deferred对象使用resolve()函数改变了Deferred对象的当前状态为完成并执行与done()相关的函数。reject()函数改变了Deferred对象的当前状态为失败并执行与fail()相关的函数。
下面是一个关于deferred的简单例子:
var dtd = $.Deferred(); //生成一个deferred对象。
var wait =function(dtd){ //定义函数 并传入deferred对象。
alert("执行了"); //函数体
dfd.resolve(); //手动改变deferred对象的运行状态从“未完成”到"已完成",立即触发done()方法。
};
$.when(wait(dtd)) //$.when可以为多个操作指定同一个回调函数 以逗号分隔开
.done(function(){ alert("成功"); }) //指定操作成功时的回调函数
.fail(function(){ alert("失败"); }); //指定操作失败时的回调函数
.then(function(){ alert("成功失败");}) //done(),fail(),progress()操作成功或失败执行的回调函数
暴露在外面的deferred 为全局对象,所以它的执行状态可以从外部改变。为了不把 deferred 对象直接暴露出来,函数体最后需返回 deferred.promise() 返回的对象只会暴露判断和处理状态的方法 ,而不会暴露改变状态的方法如:
<pre>
var wait = function(){
var dtd = $.Deferred(); // 新建一个deferred对象
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态
};
setTimeout(tasks, 500);
return dtd.promise();
};
$.when( wait())
.done(function(){ alert("成功"); })
.fail(function(){ alert("失败"); });
</pre>
在ajax中应用的实例:
<pre>
function API(api_url, method, data) {
var dtd = $.Deferred();
$.ajax({
url: api_url,
type: method,
data: data,
success: function (response) {
dtd.resolve(response);
},
error: function (error) {
dtd.reject(error);
}
});
return dtd.promise();
}
API()
.done(function (response) {
console.log('成功');
})
.fail(function (error) {
console.log('失败');
})
</pre>
jQuery deferred的优点:
可以给一个操作提供多个回调函数。
<pre>
complete1()
.done(function(){ alert("first success callback!");} )
.fail(function(){ alert("there is an error!"); } )
.done(function(){ alert("second success callback!");} );
</pre>
也可以给多个操作提供同一个回调函数。
<pre>
$.when(complete1() , complete2())
.done(function(){ alert("success");} )
.fail(function(){ alert("error"); } )
</pre>