1.作用
deferred对象是一个延迟对象,意思是函数延迟到某个点才开始执行,改变执行状态的方法有两个(成功:resolve和失败:reject),分别对应两种执行回调(成功回调函数:done和失败回调函数fail)
2.$.when()
【文字转载于菜鸟教程】 deferred1.html
在多个延迟对象传递给jQuery.when() 的情况下,该方法返回一个新的"宿主"延迟对象,当所有的延迟对 象被受理(resolve)时,该方法才会受理它的宿主延迟对象。当其中有一个延迟对象被拒绝(rejected)时, 该方法就会拒绝它的宿主延迟对象。当宿主对象被受理时,doneCallbacks(受理回调)将被执行。
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<script>
var d1 = $.Deferred();
var d2 = $.Deferred();
var d3 = $.Deferred();
$.when( d1, d2, d3 ).done(function ( v1, v2, v3 ) {
console.log( v1 ); // v1 is undefined
console.log( v2 ); // v2 is "abc"
console.log( v3 ); // v3 is an array [ 1, 2, 3, 4, 5 ]
});
d1.resolve();
d2.resolve( "abc" );
d3.reject( 1, 2, 3, 4, 5 );
</script>
</body>
</html>
3. $.Deferred()
deferred对象的链式调用 deferred2.html
参照:https://www.runoob.com/jquery/misc-jquery-deferred.html
then()
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<script>
$.Deferred(function(dfd){
setTimeout(function(){
console.log("1执行完毕!");
dfd.resolve(1);
},4000);
return dfd;
})
.then(function(value){
var deferred = $.Deferred();
setTimeout(function(){
console.log("2执行完毕!");
deferred.resolve(value + 1);
},3000);
return deferred;
})
.then(function(value){
var deferred = $.Deferred();
setTimeout(function(){
console.log("3执行完毕!" + value);
deferred.resolve();
},2000);
return deferred;
});
</script>
</body>
</html>
4.done()与then()区别
done返回当前的的deferred object,当前done方法中callback的返回值不会被传递 deferred3.html
then返回一个新的deferred object,当前then方法中callback的返回值会被传递(参考jquery的pipe属性)给新的callback
jquery的deferred对象的done方法和then方法都能实现链式调用,但是他们的作用是有区别的,then方法中如果你传递的方法有返回值,那么他会传递给下一个链式调用的方法。而done方法与此相反,你传递的方法就算有返回值,done方法也不会把你的返回值传给下一个链式调用的方法的。
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<script>
$.Deferred(function(dfd){
setTimeout(function(){
console.log("1执行完毕!");
dfd.resolve(1);
},4000);
return dfd;
})
.done(function(value){
var deferred = $.Deferred();
setTimeout(function(){
console.log("2执行完毕!");
deferred.resolve(value + 1);
},3000);
return deferred;
})
.done(function(value){
var deferred = $.Deferred();
setTimeout(function(){
console.log("3执行完毕!" + value);
deferred.resolve();
},2000);
return deferred;
});
</script>
</body>
</html>
结果:
1执行完毕!
deferred3.html:29 3执行完毕!1
deferred3.html:21 2执行完毕!
5.then() 同上
deferred4.html
<head>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<script>
var dfd = function() {
var deferred = $.Deferred();
setTimeout(function() {
console.log("执行完毕1");
deferred.resolve(1);
},2000);
return deferred;
};
$.when(dfd())
.then(function(value){
var deferred = $.Deferred();
setTimeout(function() {
console.log("执行完毕2");
console.log('value = ' + value);
deferred.resolve(value + 1);
},3000);
return deferred;
})
.then(function(value){
var deferred = $.Deferred();
setTimeout(function() {
console.log("执行完毕3");
console.log('value = ' + value);
deferred.resolve(value + 1);
},2000);
return deferred;
});
</script>
</body>
</html>
6.then()与done()结合使用
var defer = jQuery.Deferred();
defer.done(function (a, b) {
console.log("a = " + a + "b = " + b); //2,3 d1.resolve(2,3)
return a * b;
}).done(function (result) {
console.log("result = " + result); //2 d1.resolve(2,3)
}).then(function (a, b) {
console.log("a = " + a + "b = " + b); //2,3 d2.resolve(6)
return a * b;
}).done(function (result) {
console.log("result = " + result); //6 d2.resolve(6)
}).then(function (a, b) {
console.log("a = " + a + "b = " + b); //6,undefined d2.resolve(6)
return a * b; //d3.resolve(NaN)
}).done(function (result) {
console.log("result = " + result); //NaN
});
defer.resolve(2, 3); //d1
分析:
1、第一个done和第二个done都返回了defer.resolve( 2, 3 )
2、done中callback的返回值不会被传递
3、第二个done只有一个参数,接收了defer.resolve( 2, 3 )的第一个参数2,所以result是2
4、第一个then接收defer.resolve( 2, 3 ),接收两个参数,result是6,同时新建一个deferred object,传递result给deferred object
5、第三个done接收到了这个新的deferred object和传递的result,打印结果是6,并把这个新的deferred object传递给第二个then
6、第二个then现在接收新的deferred object,它只有一个参数,是result,所以参数b没有定义,返回的结果是NaN,同时又新建一个deferred object
7、第四个done接收一个新建的deferred object,传递的参数是NaN,打印的结果自然就是NaN
deferred.done() 函数当Deferred(延迟)对象被受理时,调用添加的处理程序。
提示:该方法接受一个或者多个参数。deferred.done() 返回的是一个 Deferred 对象, 可以连接其他的延迟对象方法,包括额外的 .done() 方法。当Deferred 对象得到解决时,回调函数按它们被添加时的顺序执行,并且可以作为参数传递给如下的方法使用:resolve,resolveWith。【参照csdn博文】
7. done()与then()总结
deferred.done也没有对应任何原生Promise方法,千万不要以为deferred.done对应单参数的new Promise().then,因为deferred.done连缀书写的话,各个回调函数是并列关系,回调函数里面如果有异步任务,会导致执行顺序不符合你的期待。可以使用deferred.then连缀来解决这个问题。
(3)deferred.then是jQuery中唯一可以传递延迟状态的方法。其实在1.8版本之前,没有任何方法可以传递延迟状态,只不过1.8版本开始,jQ的开发者们给then赋予了传递延迟状态的能力,这时候,很多使用者误以为done和fail等也可以传递延迟状态,其实并不是,记住,直至本文完稿为止,只有then方法有这个能力。
再具体说,就是then方法后面可以接done、fail等方法,then可以把延迟状态传递给done和fail等方法,但是,done、fail方法后面不可以接then方法,说白了done、fail就是延迟链的终点,不会再有延迟对象传递。这跟原生Promises是不一样的。【参照博文】