jQuery规定,deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是"已失败",调用fail()方法指定的回调函数;如果执行状态是"未完成",则继续等待,或者调用progress()方法指定的回调函数(jQuery1.7版本添加)。
//最佳做法
var wait = function(){var dtd = $.Deferred(); // 内部新建一个deferred对象
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变deferred对象的执行状态//dtd.reject();
};
setTimeout(tasks,5000);
return dtd;
};先介绍两个重要的方法Deferred.done,Deferred.fail
Deferred.done接收一个函数或者一个函数的数组作为参数,当promise成功返回resolved时触发该方法的执行。
Deferred.fail接收一个函数或者一个函数的数组作为参数,当promise成功返回rejected时触发该方法的执行
如果传给$.when的参数不是一个Deferred对象,则$.when将该参数视为一个resolved的Deferred对象,如果没有其他的Deferred对象传入,则触发Deferred.done执行
例如下面这个例子,fail方法永远不会被触发
- <!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.js'></script>
<script type='text/javascript'>
//live at jsfiddle.net/Ed5S9
$(function(){
function fib() {
var int1 = 0,
int2 = 1,
int3,
sequence = "<li>0</li><li>1</li>";
for ( var i = 3; i <= 100; i++ ) {
int3 = int1 + int2;
int1 = int2;
int2 = int3;
sequence += "<li>"+int3+"</li>"
}
$( "#numbers" ).append( sequence ).show( 1000 );
}
function success() {
$( "h1" ).text( "Fibonacci!" );
}
function failure() {
$("h1" ).text( "No numbers?" );
}
$(function(){
$.when( fib() )
.done( success )
.fail( failure );
});
});
</script>
</head>
<body>
<div id="main">
<h1></h1>
<ul id="numbers" style="display:none">
</ul>
</div>
</body></html>
正确的写法如下
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.js'></script>
<script type='text/javascript'>
//live at jsfiddle.net/5qAMD
$(function(){
function fib() {
return $.Deferred(function() {
var int1 = 0,
int2 = 1,
int3, sequence = "<li>0</li><li>1</li>";
for (var i = 3; i <= 100; i++) {
int3 = int1 + int2;
int1 = int2;
int2 = int3;
sequence += "<li>" + int3 + "</li>"
}
$("#numbers")
.append(sequence)
.show(1000, this.resolve);
}).promise();
}
function success() {
$( "h1" ).text( "Fibonacci!" );
}
function failure() {
$ ("h1" ).text( "No numbers?" );
}
$(function(){
$.when( fib() )
.done( success )
.fail( failure );
});
});
</script>
</head>
<body>
<div id="main">
<h1></h1>
<ul id="numbers" style="display:none">
</ul>
</div>
</body>
</html>相比于$.post(),$.get()于$.ajax()方法,jQuery为Deferred对象提供了一个别名Deferred.then
第一个参数处理resolved promise情况
第二个参数处理rejected promise情况
例如:
$.when(fib())
.then( success, failure );由于Deferred方法是可以链式的,所以Deferred方法可以与.done(),.fail()甚至其他的.then()一起调用
在ajax中使用Deferred方法,由于在jQuery1.5中使用了Deferred重写了$.ajax(),jqXHR,XMLHttpRequest,所以使其完全具备了Deferred的任何方法
function getStatus() {
return $.ajax({
url: "/status/json/",
dataType: "json"
}
)
}
function updateStatus(data) {
var $update = $("<ul />"),
$statusbar = $("#statusbar"),
html = "",
data = data.statusMessages;
for (var i = 0, test = statusMessages.length; i < test; i++) {
html += "<li>" + statusMessages[i] + "</li>";
}
@@@ same bug as above, don't think data.length is what you want given its binding to data.status. AM@@@
$update.append(html);
$statusbar.append($update);
$statusbar.slideDown(1000);
}
$.when(getStatus())
.done(updateStatus)总结:
(1) $.Deferred() 生成一个deferred对象。
(2) deferred.done() 指定操作成功时的回调函数
(3) deferred.fail() 指定操作失败时的回调函数
(4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
(5) deferred.resolve([arg]) 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。**resolve([arg])方法和reject([arg])方法可以接受一个可选参数,该可选参数分别在done()和fail()的执行函数中获取。
(6)deferred.reject([arg]) 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。
(7) $.when() 为多个操作指定回调函数。
(8)deferred.then()
如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。
(9)deferred.always()
这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
$.ajax( "test.html" )
.always( function() { alert("已执行!");} );(10)deferred.state
放回三个值pending,resovled,rejected分别代表未完成,已完成,失败
(11)Deferred.progress([arg])和Deferred.notify([arg])跟踪进度 jQuery1.7中新增
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.js'></script>
<script type='text/javascript'>
$(function(){
var longRunning = function() {
return $.Deferred(function(dfd) {
dfd.notify( "operation started" )
var callback = function() {
dfd.notify( "operation finished" );
dfd.resolve();
}
setTimeout( callback, 5000 );
}).promise();
}
longRunning().progress(
function( notification ) {
$( "#notifier" ).text( notification ).fadeIn( 500 );
}).done(function() {
$( "#notifier" ).css({
"color" : "green",
"font-weight" : "bold"
})
});
});
</script>
</head>
<body>
<div id="notifier" style="display:none"></div>
</body>
</html>