今天在项目中遇到了Deferred()的方法,虽然项目中使用的是dojo,但是其实各个框架都是相通的,以前都没有遇到过,所以今天就在网上找了些资料学习了一下:
定义和用法:
$.Deferred() 是一个构造函数,用来返回一个链式实用对象方法来注册多个回调,并且调用回调队列,传递任何同步或异步功能成功或失败的状态。
提示:
语法
$.Deferred( [beforeStart ] )
$.ajax('data/url')
.done(function(response, statusText, jqXHR){
console.log(statusText);
})
.fail(function(jqXHR, statusText, error){
console.log(statusText);
})
,always(function(){
console.log('I will always done.');
});
1.done,fail,progress都是给回调列表添加回调,因为jQuery的Deferred内部使用了其$.Callbacks对象,并且增加了memory的标记,
所以如果我们第一次触发了相应的回调列表的回调即调用了resolve,resolveWith,reject,rejectWith或者notify,notifyWith这些相应的方法,当我们再次给该回调列表添加回调时,就会立刻触发该回调了,
即使用了done,fail,progress这些方法,而不需要我们手动触发。jQuery的ajax会在请求完成后就会触发相应的回调列表。所以我们后面的链式操作的注册回调有可能是已经触发了回调列表才添加的,所以它们就会立刻被执行。
2.always方法则是不管成功还是失败都会执行该回调。
3.then方法会返回一个新的Deferred对象
$.ajax({
url: 't2.html',
dataType: 'html',
data: {
d: 4
}
}).then(function(){
console.log('success');
},function(){
console.log('failed');
}).then(function(){
console.log('second');
return $.ajax({
url: 'jquery-1.9.1.js',
dataType: 'script'
});
}, function(){
console.log('second f');
return $.ajax({
url: 'jquery-1.9.1.js',
dataType: 'script'
});
}).then(function(){
console.log('success2');
},function(){
console.log('failed2');
});
上面的代码,如果第一个对t2.html的请求成功输出success,就会执行second的ajax请求,接着针对该请求是成功还是失败,执行success2或者failed2。
如果第一个失败输出failed,然后执行second f的ajax请求(注意和上面的不一样),接着针对该请求是成功还是失败,执行success2或者failed2。
理解这些对失败处理很重要。
将我们上面序列化异步操作的代码使用then方法改造后,代码立马变得扁平化了,可读性也增强了:
var req1 = $.get('api1/data');
var req2 = $.get('api2/data');
var req3 = $.get('api3/data');
req1.then(function(req1Data){
return req2.done(otherFunc);
}).then(function(req2Data){
return req3.done(otherFunc2);
}).then(function(req3Data){
doneSomethingWithReq3();
});
4.接着介绍$.when的方法使用,主要是对多个deferred对象进行并行化操作,当所有deferred对象都得到解决就执行后面添加的相应回调。
$.when(
$.ajax({
url: 't2.html'
}),
$.ajax({
url: 'jquery-1.9.1-study.js'
})
).then(function(FirstAjaxSuccessCallbackArgs, SecondAjaxSuccessCallbackArgs){
console.log('success');
}, function(){
console.log('failed');
});
如果有一个失败了都会执行失败的回调。
将我们上面并行化操作的代码改良后:
$.when(
$.get('api1/data'),
$.get('api2/data'),
$.get('api3/data'),
{ key: 'value' }
).done();