使用jQuery Deferred对象实现Promise

注:这篇文章翻译自这里
promise就像婴儿,生着容易养着难。–未知作者
回想一下怎么为DOM元素添加一个鼠标点击事件。你可以这么搞,elem.onclick = handler。这么干有一个问题就是不能添加多个handler,如果添加多个,最后一个添加的handler生效。所幸有一个DOM函数可以解决这个问题。对,你想的没错,就是addEventListener()。话说ajax请求也有这么一个类似的问题,就是只能为ajax请求添加一个回调函数。为了解决这个问题,jQuery 1.5之后的版本的Deferred对象允许你为ajax请求添加多个回调函数。

什么是promise

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
});

组合promise

$.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状态

promise有三种状态:unfulfilled, resolved 和 rejected。回调队列中的函数等待这三个状态,随后执行。例如,如果ajax调用成功了,那么会调用$.resolved()函数,设置promise状态为resolved,这时“done”函数才会执行。

写一个自己的Deferred进程

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() + '.'); }
);      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值