前言:
什么叫做递延对象,生成一个递延对象只需调用jQuery.Deferred函数,deferred这个单词译为延期,推迟,即延迟的意思,那么在jQuery中
又是如何表达延迟的呢,从递延对象中的then方法或许能找到这种延迟的行为,本文重点解读递延对象中的then方法
上一篇:jQuery回调、递延对象总结(上篇)—— jQuery.Callbacks
设计思路:
在递延对象构造中,分别有三组回调对象,每一组回调对象都有与之对应的行为(action,add listener),和状态(final state),
这些行为都归纳为递延对象中的(触发回调,添加函数到回调列表中等)方法
jQuery.Deferred构造
源码
Deferred构造源码除了then函数源码外,其他都非常简单,这里不做过多解读,后面将重点讨论then方法
View Code
神奇的then方法
在实际项目应用中,一个页面或许有多个ajax请求,你可能会这样做:
$.ajax({ url1, ... });
$.ajax({ url2, ... });
$.ajax({ url3, ... });
...
这样做的缺点:
1、多个ajax同时发送请求,可能会造成服务器压力,对于富应用页面来说,如果请求过多,那是必然的;
2、对于页面底部,或者说首屏不展示给用户浏览的部分需要发送的ajax请求,没有必要让它一开始加载页面后就发送请求,这样会造成页面响应缓慢
jQuery递延对象中的then方法好像天生就是为了解决以上问题而设计的,它可以按照顺序依次处理多个异步请求,即第一个请求处理完后,
再处理第二个请求,以此类推,这样既可以减轻服务器压力,又可以先发送首屏(从上到下)页面部分的请求,使页面响应更快
来看看一段非常优雅的实例代码
var promiseA = $.get(urlA);
promiseA.always(doneFnA, failFnA, progressFnA);
var promiseB = promiseA.then(function(){
return $.get(urlB);
});
或者你也可以这样写,但并不建议:
View Code
上面代码是如何运行的呢:
首先发送第一个ajax请求,当promiseA对象执行过resolve(或reject、notify)后,即:第一个请求成功或失败后,将依次执行回调doneFnA
(或failFnA、progressFnA),then中的匿名函数(注意代码的顺序,之前代码顺序有误,把promiseA.always放在了then方法执行之后,现已改过来了),
匿名函数中发送第二个ajax请求,当请求成功或失败后,将执行对应的回调函数(doneFnB或failFnB、progressFnB)
衍生后的代码
var promiseA = $.get(urlA);
// 这里添加promiseA的回调
var promiseB = promiseA.then(function(){
return $.get(urlB);
});
// 这里添加promiseB的回调
var promiseC = promiseB.then(function(){
return $.get(urlC);
});
// 这里添加promiseC的回调
var promiseD = promiseC.then(function(){
return $.get(urlD);
});
// 这里添加promiseD的回调
再来看看then函数中的构造源码,通过上面的实例分析,相信眼前的你会恍然大悟的
promise = {
then: function( /* fnDone, fnFail, fnProgress */ ) {
var fns = arguments;
// 返回后的promise对象与newDefer对应
return jQuery.Deferred(function( newDefer ) {
jQuery.each( tuples, function( i, tuple ) {
var action = tuple[ 0 ],
fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
// deferred[ done | fail | progress ] for forwarding actions to newDefer
// 为第一个递延对象添加回调
deferred[ tuple[1] ](function() {
var returned = fn && fn.apply( this, arguments );
// 如果回调返回的是一个递延对象,newDefer将根据这个返回的递延对象的状态来触发行为
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
}
// 如果回调返回的不是一个递延对象,newDefer将根据第一个(deferred)递延对象的状态来触发行为
else {
newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}
});
});
fns = null;
}).promise();
}
}
原文链接:http://www.2cto.com/kf/201401/271185.html