注:这篇文章翻译自这里
promise就像婴儿,生着容易养着难。–未知作者
回想一下怎么为DOM元素添加一个鼠标点击事件。你可以这么搞,elem.onclick = handler
。这么干有一个问题就是不能添加多个handler,如果添加多个,最后一个添加的handler生效。所幸有一个DOM函数可以解决这个问题。对,你想的没错,就是addEventListener()
。话说ajax请求也有这么一个类似的问题,就是只能为ajax请求添加一个回调函数。为了解决这个问题,jQuery 1.5之后的版本的Deferred对象允许你为ajax请求添加多个回调函数。
jQuery 1.5版本之前的ajax调用是这样的:
$.ajax({
url: "server/source.txt",
success: successFun,
error: errorFun
})
jQuery 1.5版本之后的ajax调用会返回一个实现了CommonJS Promises/A interface接口的对象(jQuery XMLHttpRequest (jqXHR))。
var promise = $.ajax({url: "server/source.txt"});
promise.done(successFun);
promise.fail(failFun);
promise.always(alwaysFun);
always()
函数里面的回调函数alwaysFun
不管ajax调用返回失败还是成功都会触发。
由于done()
,fail()
和always()
返回的都是jqXHR对象,所以三个函数可以链式调用:
$.ajax({url: "server/source.txt"}).done(successFun).fail(failFun).always(alwaysFun);
你还可以把这个jqXHR对象对象存储在一个变量里,以便随时再次为它添加回调函数:
var jqXHR = $.ajax({url: "server/source.txt"}).done(successFun).fail(failFun).always(alwaysFun);
// do some stuff here...
jqXHR.always(anathorAlwaysFun);
可以使用promise接口的than()
函数将ajax回调函数写在一块,jQuery 1.8版本之前你可以将函数数组传递给than()
函数:
$.ajax({url: "/ServerResource.txt"}).then([successFunction1, successFunction2, successFunction3], [errorFunction1, errorFunction2]);
//same as
var jqxhr = $.ajax({
url: "/ServerResource.txt"
});
jqxhr.done(successFunction1);
jqxhr.done(successFunction2);
jqxhr.done(successFunction3);
jqxhr.fail(errorFunction1);
jqxhr.fail(errorFunction2);
jQuery 1.8版本之后不用往than()
函数中传数组了,可以这么干:
var promise = $.ajax({
url: "/ServerResource.txt"
});
promise.then(successFunction, errorFunction);
var promise = $.ajax({
url: "/ServerResource.txt"
});
promise.then(successFunction); //no handler for the fail() event
than()
函数var promise = $.ajax("/myServerScript1");
function getStuff() {
return $.ajax("/myServerScript2");
}
promise.then(getStuff).then(function(myServerScript2Data){
// Do something with myServerScript2Data
});
$.when()
可以接受多个jqXHR对象作为参数,如果这几个jqXHR对象都resolved,那么$.when()
返回一个新的resolved状态的jqXHR对象。否则返回一个rejected状态的jqXHR对象。
var jqxhr1 = $.ajax("/ServerResource1.txt");
var jqxhr2 = $.ajax("/ServerResource2.txt");
$.when(jqxhr1, jqxhr2).done(function(jqxhr1, jqxhr2) {
// Handle both XHR objects
alert("all complete");
});
promise有三种状态:unfulfilled, resolved 和 rejected。回调队列中的函数等待这三个状态,随后执行。例如,如果ajax调用成功了,那么会调用$.resolved()
函数,设置promise状态为resolved,这时“done”函数才会执行。
var timer;
$('#result').html('waiting...');
var promise = process();
function process() {
var deferred = $.Deferred();
timer = setTimeout(function () {
deferred.notify();
}, 1000);
setInterval(function () {
clearInterval(timer);
deferred.resolved();
}, 10000);
return deferred.promise();
}
promise.done(function () {
$('#result').html('done.');
});
promise.progress(function () {
$('#result').html($('#result').html() + '.');
});
当然,也可以使用then()
函数:
process().then(
function () { $('#result').html('done.'); },
null,
function () { $('#result').html($('#result').html() + '.'); }
);