原文出自http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html,在此基础上进行了下简化
/**
* 1.Deffered对象
*deffered对象就是jQuery的回调函数解决方案,含义延迟到未来某个点再执行
* 产生背景:开发网站时,经常会遇到耗时长的javascript操作,既有异步操作,也有同步操作,它们都不是能立即得到结果,解决方法是为其指定回调函数。
* 可是jQuery的回调功能不好,便有了Deffered
*/
/**
* 2.ajax操作---链式写法
*/
js代码示例
//传统
$.ajax({
async:false,
url:"index.html",
success:function(data){
console.log("调用成功!");
},
error:function(){
console.log("调用失败!");
}
});
//链式写法-新写法
//$.ajax()执行完毕,若使用低于1.5.0版本jQuery,返回XHR对象,无法进行链式操作;若高于1.5.0版本,返回deferred对象,可进行链式操作
$.ajax("index.html").done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
/**
* 3.指定同一操作的多个回调函数
* 作用:允许开发人员自由添加多个回调函数,按照添加顺序执行。
*/
js代码示例
$.ajax("index.html").done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
}).done(function(){
console.log("two done ok!");
});
/**
* 4.为多个操作指定回调函数
*/
js代码示例
$.when($.ajax("index1.html"), $.ajax("index2.html")).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
//先执行两个操作$.ajax("index1.html")和$.ajax("index2.html"),如果都成功了,就运行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数
/**
* 5.Deferred对象方法操作
* 最大优点:把这一套回调函数接口,从ajax操作扩展到了所有操作
*/
js代码示例
var wait = function (){
var tasks = function (){
alert("success!");
};
setTimeout(tasks,5000);
}
$.when(wait()).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
//由于$.when()的参数只能是deferred对象,done()方法会立即执行,起不到回调函数的作用。
//正确写法
var defObj = $.Deferred();
var wait = function (defObj){
var tasks = function (){
alert("success!");
defObj.resolve();//改变deferred对象的执行状态,将defObj对象的执行状态从"未完成"改为"已完成",
};
setTimeout(tasks,5000);
return defObj;
}
$.when(wait(defObj)).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
//$.Deferred().resolve()与$.Deferred().reject()
/**
* 执行状态:jQuery规定,deferred对象有三种执行状态----未完成,已完成和已失败。
* 若执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;若执行状态是"已失败",
* 调用fail()方法指定的回调函数;若执行状态是"未完成",则继续等待,或者调用progress()方法指定的回调函数(jQuery1.7版本添加)。
*/
js代码示例
var defObj = $.Deferred();
var wait = function (defObj){
var tasks = function (){
alert("success!");
defObj.reject();//改变deferred对象的执行状态,将defObj对象的执行状态从"未完成"改为"已失败"
};
setTimeout(tasks,5000);
return defObj;
}
$.when(wait(defObj)).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
//$.Deferred().promise()
/**
* defObj是一个全局对象,所以它的执行状态可以从外部改变
* 作用;在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),
* 屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。
* */
js示例代码
var defObj = $.Deferred();
var wait = function (defObj){
var tasks = function (){
alert("success!");
defObj.resolve();//改变deferred对象的执行状态,将defObj对象的执行状态从"未完成"改为"已完成",
};
setTimeout(tasks,5000);
return defObj;
}
$.when(wait(defObj)).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
defObj.resolve();
//正确写法
var defObj = $.Deferred();
var wait = function (defObj){
var tasks = function (){
alert("success!");
defObj.resolve();//改变deferred对象的执行状态,将defObj对象的执行状态从"未完成"改为"已完成",
};
setTimeout(tasks,5000);
return defObj.promise(); //返回promise对象
}
$.when(wait(defObj)).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
defObj.resolve();//此时,这个语句是无效的
//更优化代码
var wait = function (){
var defObj = $.Deferred();
var tasks = function (){
alert("success!");
defObj.resolve();//改变deferred对象的执行状态,将defObj对象的执行状态从"未完成"改为"已完成",
};
setTimeout(tasks,5000);
return defObj.promise(); //返回promise对象
}
$.when(wait()).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
//另外一种方案,阻止执行状态被外部改变
$.Deferred(wait).done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
//直接在wait对象上部署deferred接口
var defObj = $.Deferred(); // 生成Deferred对象
var wait = function(defObj){
var tasks = function(){
alert("执行完毕!");
defObj.resolve(); // 改变Deferred对象的执行状态
};
setTimeout(tasks,5000);
};
defObj.promise(wait);//关键,作用就是在wait对象上部署Deferred接口。正是因为有了这一行,后面才能直接在wait上面调用done()和fail()。
wait.done(function(){
console.log("done ok!");
}).fail(function(){
console.log("done fail!");
});
wait(defObj);
/**
* 6.deferred对象的方法
*
* (1) $.Deferred() 生成一个deferred对象。
* (2) deferred.done() 指定操作成功时的回调函数
* (3) deferred.fail() 指定操作失败时的回调函数
* (4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
* (5) deferred.resolve() 手动改变deferred对象的运行状态为"已完成",从而立即触发done()方法。
* (6) deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为"已失败",从而立即触发fail()方法。
* (7) $.when() 为多个操作指定回调函数。
* 除了这些方法以外,deferred对象还有二个重要方法,上面的教程中没有涉及到。
* (8)deferred.then()有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。
* $.when($.ajax( "/main.php" )).then(successFunc, failureFunc );
* 如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。
* (9)deferred.always()
* 这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
* $.ajax( "test.html" ).always( function() { alert("已执行!");} );
* */