阅读了阮一峰老师的jQuery的deferred对象详解,自己整理一下。
随着WEB单页应用的普及,现在越来越多的页面逻辑已经交由JS代码来处理,其中难免有向后台请求资源等费时操作。
由于浏览器是单线程执行JS代码, 所以为了防止在请求的同时页面出现卡死的现象,提出了异步请求(ajax)。
我们可以将渲染返回数据的操作在异步请求的回调中执行, 避免页面卡死。
jQuery的ajax方法最典型的回调方法就是success和error,已经相当常用了。
而Deferred对象提供了更方便更强大的方法控制回调的逻辑, Deferred对象是早在jQuery1.5版本时就引入的特性(2011年),支持jQuery的链式调用语法。
简单理解就是: Deferred的实例可以注册多个callback函数到一个队列中去,并根据Deferred实例的状态来有选择的,顺序的执行这些回调函数。
可以通过调用jQuery.Deferred()方法来获得一个Deferred Object实例。
var d = jQuery.Deferred() // create Deferred Object
Deferred对象有三种执行状态:
1. pending
2. resolved
3. rejected
可以在Deferred对象上调用state()方法获取。
三种状态代表的含义见名知意。
var d = jQuery.Deferred() // create Deferred Object
console.log(d.state()); // return 'pending'
function executeTasks() {
var _tasks = function() {
// 'finish tasks here'
d.resolve(); // notify Deferred Object has been resolved
console.log(d.state()); // return 'resolved'
}
setTimeout(_tasks, 3000);
}
executeTasks();
var d = jQuery.Deferred() // create Deferred Object
function executeTasks() {
var _tasks = function() {
// 'finish tasks here'
d.reject(); // notify Deferred Object has been rejected
console.log(d.state()); // return 'rejected'
}
setTimeout(_tasks, 3000);
}
executeTasks();
var d = jQuery.Deferred() // create Deferred Object
d.done(function(){
console.log('I am done. n.n'); // 1
}).done(function(){
console.log('I am done again. n.n'); // 2
})
function executeTasks() {
var _tasks = function() {
// 'finish tasks here'
d.resolve(); // notify Deferred Object has been resolved
}
setTimeout(_tasks, 3000);
}
executeTasks();
var d = jQuery.Deferred() // create Deferred Object
d.done(function(){
console.log('I am done. n.n'); // 1
}).done(function(){
console.log('I am done again. n.n'); // 2
}).fail(function(){
console.log('I am rejected. >.<');
})
function executeTasks() {
var _tasks = function() {
// 'finish tasks here'
d.reject(); // notify Deferred Object has been rejected
}
setTimeout(_tasks, 3000);
}
executeTasks();
always函数顾名思义,无论Deferred对象最终获得resolved状态还是rejected状态,该回调函数总是会被调用。
var d = jQuery.Deferred() // create Deferred Object
d.fail(function(){
console.log('I am rejected. >.<');
}).always(function(){
console.log('I am always here. =.= ');
});
function executeTasks() {
var _tasks = function() {
// 'finish tasks here'
d.reject(); // notify Deferred Object has been rejected
d.state(); // return 'rejected'
}
setTimeout(_tasks, 3000);
}
executeTasks();
when()方法使得Deferred对象支持多个异步操作都完成后,才执行统一定义的回调。
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.resolve( 1, 2, 3, 4, 5 );
假若所有Deferred对象获得resolved状态,执行done回调。
假若其中至少一个Deferred对象获得rejected状态,执行fail回调。
function getPromise() {
return $.Deferred().promise();
}
try {
getPromise().resolve("a");
} catch(err){
console.log(err);
}
最常用的应用是jQuery的ajax方法,该方法返回的就是一个Deferred对象的Promise()对象。
$.ajax("/home/news/")
.done(function(){ alert('I am done. n.n');} )
.fail(function(){ alert('I am rejected. >.<'); } )
这样做的好处是避免在Deferred对象的创建者的作用范围外改变Deferred对象的执行状态。