jQuery中deferred對象使用方法詳解

字號:


    在jquery1.5之后的版本中,加入了一個deferred對象,也就是延遲對象,用來處理未來某一時間點發(fā)生的回調(diào)函數(shù)。同時,還改寫了ajax方法,現(xiàn)在的ajax方法返回的是一個deferred對象。
    那就來看看deferred對象的用法。
    1.ajax的鏈?zhǔn)交卣{(diào) 
    // ajax方法返回的是一個deferred對象,可以直接使用鏈?zhǔn)綄懛?BR>    $.ajax('test.json').done(function(resp){
     // done 相當(dāng)于success回調(diào),其中默認(rèn)的參數(shù)為success回調(diào)的參數(shù)
     alert('success');
    }).fail(function(){
     // fail 相當(dāng)于error回調(diào)
     alert('error');
    });
    還可以同時寫多個回調(diào),會按照順序依次執(zhí)行 
    $.ajax('test.json').done(function(resp){
     // done 相當(dāng)于success回調(diào),其中默認(rèn)的參數(shù)為success回調(diào)的參數(shù)
     alert('success');
    }).done(function(){
     // do something...
    }).done(function(){
     // do something...
    });
    deferred對象還有一個then方法,其實它是一個整合done和fail的方法,它接受一到兩個參數(shù),如果有兩個參數(shù),那么第一個就是done方法的回調(diào)函數(shù),第二個是fail方法的回調(diào)函數(shù)。如果只有一個參數(shù),那就是done方法的回調(diào)函數(shù)。 
    var success = function(){
     alert('success'); 
    };
    var error = function(){
     alert('error');
    };
    // 兩個參數(shù)
    $.ajax('test.json').then(success, error);
    // 一個參數(shù)
    $.ajax('test.json').then(success);
    jQuery還提供了一個$.when(deferreds)的方法來執(zhí)行一個或多個延遲對象的回調(diào)函數(shù),當(dāng)它的參數(shù)是延遲對象時,它會在所有延遲對象代表的異步執(zhí)行完后再執(zhí)行相應(yīng)的回調(diào)函數(shù) 
    $.when($.ajax('test.json'), $.ajax('demo.json')) .done(function(){
     alert('success'); 
    }).fail(function(){
     alert('error');
    });
    很好理解,只有當(dāng)所有異步都成功時,才會執(zhí)行done方法中的回調(diào),否則會執(zhí)行fail方法中的回調(diào),同樣好理解的是的done方法中回調(diào)函數(shù)的默認(rèn)參數(shù)數(shù)量則和when方法參數(shù)數(shù)量相同。
    而如果when方法中傳入的只是普通對象,不是deferred對象時,會立即執(zhí)行done方法中的回調(diào),回調(diào)函數(shù)的默認(rèn)參數(shù)為傳入when方法的對象本身。
    // 當(dāng)傳入when方法的參數(shù)只是普通對象時
    $.when({test: 'test'}).done(function(resp){
     console.log(resp.test); // 'test' 
    }).fail(function(){
     // 由于傳入的對象不是deferred對象,那么就不會調(diào)用fail中的回調(diào)了 
    }) 
    當(dāng)你需要兩個甚至更多的異步結(jié)束后才調(diào)用回調(diào)函數(shù),同時這些異步ajax可能還需要修改傳輸方式type或者傳數(shù)據(jù)data時,代碼就顯得很亂,可讀性很差。 
    所以就可以對ajax進(jìn)行再次封裝,提高代碼可讀性 
    var ajax = function(url, type, param){
     return $.ajax({
     url: url,
     type: type,
     data: param || {} 
     }); 
    };
    ajax('test.json').done(function(resp){
     alert('success');
    }).fail(function(){
     alert('error');
    });
    接者學(xué)習(xí),漏了一個always()方法,參數(shù)也是回調(diào)函數(shù),與done和fail不同的是,無論任何情況都執(zhí)行always方法中的回調(diào)。
    deferred對象不光可以用在jquery的ajax方法中,他提供了一系列的接口,使它的通用型大大提高。
    比如有這樣一個耗時比較久的方法
    function a(){
     function b(){
     alert('start');
     } 
     setTimeout(b, 3000); 
    } 
    如果要在這個方法之后執(zhí)行某個回調(diào),就不能用$.when()了,因為當(dāng)$.when()的參數(shù)不為deferred對象是會直接調(diào)用done或者always中的回調(diào)函數(shù)。
    這個時候就要使用deferred對象的其他方法了,還是上面的方法,做一些改寫 
    function a(){
     var def = $.Deferred(); // 創(chuàng)建deferred對象 
     function b(){
     alert('start');
     def.resolve(); // 改變deferred對象的狀態(tài)
     } 
     setTimeout(b, 3000); 
     return def;
    }
    $.when(a()).done(function(){
     alert("It's callback");
    });
    分析一下:
     1). $.Deferred()方法會創(chuàng)建一個deferred對象
     2). def.resolve()會改變deferred對象的狀態(tài),deferred對象有三種狀態(tài),未完成,成功,失敗。
     它有resolve()和reject()兩個方法,resolve方法可以把對象狀態(tài)改為成功,reject方法可以把狀態(tài)改為失敗。
     又有以上的寫法會出現(xiàn)問題,返回的deferred對象可以被外部改變狀態(tài),所以還提供了一個promise()方法,這個方法會在deferred對象的基礎(chǔ)上返回一個新的deferred對象,不同的是,返回的對象只存在可被觀察到狀態(tài),而不具備可改變其狀態(tài)的方法,類似返回了一個只讀的deferred對象。
    所以同樣的例子可以改寫成這樣 
    function a(){
     var def = $.Deferred(); // 創(chuàng)建deferred對象 
     function b(){
     alert('start');
     def.resolve(); // 改變deferred對象的狀態(tài)
     } 
     setTimeout(b, 3000); 
     return def.promise();
    }
    $.when(a().reject()).done(function(){ // reject()方法無效
     alert("It's callback");
    });
    以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助