亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

jQuery之Deferred對(duì)象詳解

 更新時(shí)間:2014年09月04日 11:09:14   投稿:junjie  
這篇文章主要介紹了jQuery之Deferred對(duì)象詳解,本文深入剖析了jQuery Deferred對(duì)象的方法屬性等內(nèi)容,需要的朋友可以參考下

deferred對(duì)象是jQuery對(duì)Promises接口的實(shí)現(xiàn)。它是非同步操作的通用接口,可以被看作是一個(gè)等待完成的任務(wù),開(kāi)發(fā)者通過(guò)一些通過(guò)的接口對(duì)其進(jìn)行設(shè)置。事實(shí)上,它扮演代理人(proxy)的角色,將那些非同步操作包裝成具有某些統(tǒng)一特性的對(duì)象,典型例子就是Ajax操作、網(wǎng)頁(yè)動(dòng)畫(huà)、web worker等等。

jQuery的所有Ajax操作函數(shù),默認(rèn)返回的就是一個(gè)deferred對(duì)象。

Promises是什么

由于JavaScript單線程的特點(diǎn),如果某個(gè)操作耗時(shí)很長(zhǎng),其他操作就必需排隊(duì)等待。為了避免整個(gè)程序失去響應(yīng),通常的解決方法是將那些排在后面的操作,寫(xiě)成“回調(diào)函數(shù)”(callback)的形式。這樣做雖然可以解決問(wèn)題,但是有一些顯著缺點(diǎn):

1.回調(diào)函數(shù)往往寫(xiě)成函數(shù)參數(shù)的形式,導(dǎo)致函數(shù)的輸入和輸出非?;靵y,整個(gè)程序的可閱讀性差;
2.回調(diào)函數(shù)往往只能指定一個(gè),如果有多個(gè)操作,就需要改寫(xiě)回調(diào)函數(shù)。
3.整個(gè)程序的運(yùn)行流程被打亂,除錯(cuò)和調(diào)試的難度都相應(yīng)增加。

Promises就是為了解決這些問(wèn)題而提出的,它的主要目的就是取代回調(diào)函數(shù),成為非同步操作的解決方案。它的核心思想就是讓非同步操作返回一個(gè)對(duì)象,其他操作都針對(duì)這個(gè)對(duì)象來(lái)完成。比如,假定ajax操作返回一個(gè)Promise對(duì)象。

復(fù)制代碼 代碼如下:

var promise = get('http://www.example.com');

然后,Promise對(duì)象有一個(gè)then方法,可以用來(lái)指定回調(diào)函數(shù)。一旦非同步操作完成,就調(diào)用指定的回調(diào)函數(shù)。
復(fù)制代碼 代碼如下:

promise.then(function (content) {
  console.log(content)
})

可以將上面兩段代碼合并起來(lái),這樣程序的流程看得更清楚。
復(fù)制代碼 代碼如下:

get('http://www.example.com').then(function (content) {
  console.log(content)
})

在1.7版之前,jQuery的Ajax操作采用回調(diào)函數(shù)。

復(fù)制代碼 代碼如下:

$.ajax({
    url:"/echo/json/",
    success: function(response)
    {
       console.info(response.name);
    }
});

1.7版之后,Ajax操作直接返回Promise對(duì)象,這意味著可以用then方法指定回調(diào)函數(shù)。

復(fù)制代碼 代碼如下:

$.ajax({
    url: "/echo/json/",
}).then(function (response) {
    console.info(response.name);
});

deferred對(duì)象的方法

$.deferred()方法

作用是生成一個(gè)deferred對(duì)象。

復(fù)制代碼 代碼如下:

var deferred = $.deferred();

done() 和 fail()

這兩個(gè)方法都用來(lái)綁定回調(diào)函數(shù)。done()指定非同步操作成功后的回調(diào)函數(shù),fail()指定失敗后的回調(diào)函數(shù)。

復(fù)制代碼 代碼如下:

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});

它們返回的是原有的deferred對(duì)象,因此可以采用鏈?zhǔn)綄?xiě)法,在后面再鏈接別的方法(包括done和fail在內(nèi))。

resolve() 和 reject()

這兩個(gè)方法用來(lái)改變deferred對(duì)象的狀態(tài)。resolve()將狀態(tài)改為非同步操作成功,reject()改為操作失敗。

復(fù)制代碼 代碼如下:

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});
deferred.resolve("hello world");

一旦調(diào)用resolve(),就會(huì)依次執(zhí)行done()和then()方法指定的回調(diào)函數(shù);一旦調(diào)用reject(),就會(huì)依次執(zhí)行fail()和then()方法指定的回調(diào)函數(shù)。

state方法

該方法用來(lái)返回deferred對(duì)象目前的狀態(tài)。

復(fù)制代碼 代碼如下:

var deferred = new $.Deferred();
deferred.state();  // "pending"
deferred.resolve();
deferred.state();  // "resolved"

該方法的返回值有三個(gè):

1.pending:表示操作還沒(méi)有完成。
2.resolved:表示操作成功。
3.rejected:表示操作失敗。

notify() 和 progress()

progress()用來(lái)指定一個(gè)回調(diào)函數(shù),當(dāng)調(diào)用notify()方法時(shí),該回調(diào)函數(shù)將執(zhí)行。它的用意是提供一個(gè)接口,使得在非同步操作執(zhí)行過(guò)程中,可以執(zhí)行某些操作,比如定期返回進(jìn)度條的進(jìn)度。

復(fù)制代碼 代碼如下:

 var userProgress = $.Deferred();
    var $profileFields = $("input");
    var totalFields = $profileFields.length
    userProgress.progress(function (filledFields) {
        var pctComplete = (filledFields/totalFields)*100;
        $("#progress").html(pctComplete.toFixed(0));
    });
    userProgress.done(function () {
        $("#thanks").html("Thanks for completing your profile!").show();
    });
    $("input").on("change", function () {
        var filledFields = $profileFields.filter("[value!='']").length;
        userProgress.notify(filledFields);
        if (filledFields == totalFields) {
            userProgress.resolve();
        }
    });

then()

then()的作用也是指定回調(diào)函數(shù),它可以接受三個(gè)參數(shù),也就是三個(gè)回調(diào)函數(shù)。第一個(gè)參數(shù)是resolve時(shí)調(diào)用的回調(diào)函數(shù),第二個(gè)參數(shù)是reject時(shí)調(diào)用的回調(diào)函數(shù),第三個(gè)參數(shù)是progress()方法調(diào)用的回調(diào)函數(shù)。

復(fù)制代碼 代碼如下:

deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

在jQuery 1.8之前,then()只是.done().fail()寫(xiě)法的語(yǔ)法糖,兩種寫(xiě)法是等價(jià)的。在jQuery 1.8之后,then()返回一個(gè)新的deferred對(duì)象,而done()返回的是原有的deferred對(duì)象。如果then()指定的回調(diào)函數(shù)有返回值,該返回值會(huì)作為參數(shù),傳入后面的回調(diào)函數(shù)。

復(fù)制代碼 代碼如下:

var defer = jQuery.Deferred();
defer.done(function(a,b){
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
});
defer.resolve( 2, 3 );

在jQuery 1.8版本之前,上面代碼的結(jié)果是:

復(fù)制代碼 代碼如下:

result = 2
result = 2
result = 2

在jQuery 1.8版本之后,返回結(jié)果是
復(fù)制代碼 代碼如下:

result = 2
result = 6
result = NaN

這一點(diǎn)需要特別引起注意。
復(fù)制代碼 代碼如下:

$.ajax( url1, { dataType: "json" } )
.then(function( data ) {
    return $.ajax( url2, { data: { user: data.userId } } );
}).done(function( data ) {
  // 從url2獲取的數(shù)據(jù)
});

上面代碼最后那個(gè)done方法,處理的是從url2獲取的數(shù)據(jù),而不是從url1獲取的數(shù)據(jù)。

利用then()會(huì)修改返回值這個(gè)特性,我們可以在調(diào)用其他回調(diào)函數(shù)之前,對(duì)前一步操作返回的值進(jìn)行處理。

復(fù)制代碼 代碼如下:

var post = $.post("/echo/json/")
    .then(function(p){
        return p.firstName;
    });
post.done(function(r){ console.log(r); });

上面代碼先使用then()方法,從返回的數(shù)據(jù)中取出所需要的字段(firstName),所以后面的操作就可以只處理這個(gè)字段了。

有時(shí),Ajax操作返回json字符串里面有一個(gè)error屬性,表示發(fā)生錯(cuò)誤。這個(gè)時(shí)候,傳統(tǒng)的方法只能是通過(guò)done()來(lái)判斷是否發(fā)生錯(cuò)誤。通過(guò)then()方法,可以讓deferred對(duì)象調(diào)用fail()方法。

復(fù)制代碼 代碼如下:

var myDeferred = $.post('/echo/json/', {json:JSON.stringify({'error':true})})
    .then(function (response) {
            if (response.error) {
                return $.Deferred().reject(response);
            }
            return response;
        },function () {
            return $.Deferred().reject({error:true});
        }
    );
myDeferred.done(function (response) {
        $("#status").html("Success!");
    }).fail(function (response) {
        $("#status").html("An error occurred");
    });

always()

always()也是指定回調(diào)函數(shù),不管是resolve或reject都要調(diào)用。

pipe方法

pipe方法接受一個(gè)函數(shù)作為參數(shù),表示在調(diào)用then方法、done方法、fail方法、always方法指定的回調(diào)函數(shù)之前,先運(yùn)行pipe方法指定的回調(diào)函數(shù)。它通常用來(lái)對(duì)服務(wù)器返回的數(shù)據(jù)做初步處理。

promise對(duì)象

大多數(shù)情況下,我們不想讓用戶從外部更改deferred對(duì)象的狀態(tài)。這時(shí),你可以在deferred對(duì)象的基礎(chǔ)上,返回一個(gè)針對(duì)它的promise對(duì)象。我們可以把后者理解成,promise是deferred的只讀版,或者更通俗地理解成promise是一個(gè)對(duì)將要完成的任務(wù)的承諾。

你可以通過(guò)promise對(duì)象,為原始的deferred對(duì)象添加回調(diào)函數(shù),查詢它的狀態(tài),但是無(wú)法改變它的狀態(tài),也就是說(shuō)promise對(duì)象不允許你調(diào)用resolve和reject方法。

復(fù)制代碼 代碼如下:

function getPromise(){
    return $.Deferred().promise();
}
try{
    getPromise().resolve("a");
} catch(err) {
    console.log(err);
}

上面的代碼會(huì)出錯(cuò),顯示TypeError {} 。

jQuery的ajax() 方法返回的就是一個(gè)promise對(duì)象。此外,Animation類(lèi)操作也可以使用promise對(duì)象。

復(fù)制代碼 代碼如下:

var promise = $('div.alert').fadeIn().promise();

$.when()方法

$.when()接受多個(gè)deferred對(duì)象作為參數(shù),當(dāng)它們?nèi)窟\(yùn)行成功后,才調(diào)用resolved狀態(tài)的回調(diào)函數(shù),但只要其中有一個(gè)失敗,就調(diào)用rejected狀態(tài)的回調(diào)函數(shù)。它相當(dāng)于將多個(gè)非同步操作,合并成一個(gè)。

復(fù)制代碼 代碼如下:

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(successFunc, failureFunc);

上面代碼表示,要等到三個(gè)ajax操作都結(jié)束以后,才執(zhí)行then方法指定的回調(diào)函數(shù)。

when方法里面要執(zhí)行多少個(gè)操作,回調(diào)函數(shù)就有多少個(gè)參數(shù),對(duì)應(yīng)前面每一個(gè)操作的返回結(jié)果。

復(fù)制代碼 代碼如下:

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(function (resp1, resp2, resp3){
    console.log(resp1);
    console.log(resp2);
    console.log(resp3);
});

上面代碼的回調(diào)函數(shù)有三個(gè)參數(shù),resp1、resp2和resp3,依次對(duì)應(yīng)前面三個(gè)ajax操作的返回結(jié)果。

when方法的另一個(gè)作用是,如果它的參數(shù)返回的不是一個(gè)Deferred或Promise對(duì)象,那么when方法的回調(diào)函數(shù)將 立即運(yùn)行。

復(fù)制代碼 代碼如下:

$.when({testing: 123}).done(function (x){
  console.log(x.testing); // "123"
});

上面代碼中指定的回調(diào)函數(shù),將在when方法后面立即運(yùn)行。

利用這個(gè)特點(diǎn),我們可以寫(xiě)一個(gè)具有緩存效果的異步操作函數(shù)。也就是說(shuō),第一次調(diào)用這個(gè)函數(shù)的時(shí)候,將執(zhí)行異步操作,后面再調(diào)用這個(gè)函數(shù),將會(huì)返回緩存的結(jié)果。

復(fù)制代碼 代碼如下:

function maybeAsync( num ) {
  var dfd = $.Deferred();
  if ( num === 1 ) {
    setTimeout(function() {
      dfd.resolve( num );
    }, 100);
    return dfd.promise();
  }
  return num;
}
$.when(maybeAsync(1)).then(function (resp){
  $('#target').append('<p>' + resp + '</p>');
});
$.when(maybeAsync(0)).then(function (resp){
  $('#target').append( '<p>' + resp + '</p>');
});

上面代碼表示,如果maybeAsync函數(shù)的參數(shù)為1,則執(zhí)行異步操作,否則立即返回緩存的結(jié)果。

實(shí)例

wait方法

我們可以用deferred對(duì)象寫(xiě)一個(gè)wait方法,表示等待多少毫秒后再執(zhí)行。

復(fù)制代碼 代碼如下:

$.wait = function(time) {
  return $.Deferred(function(dfd) {
    setTimeout(dfd.resolve, time);
  });
}

使用方法如下:
復(fù)制代碼 代碼如下:

$.wait(5000).then(function() {
  alert("Hello from the future!");
});

改寫(xiě)setTimeout方法

在上面的wait方法的基礎(chǔ)上,還可以改寫(xiě)setTimeout方法,讓其返回一個(gè)deferred對(duì)象。

復(fù)制代碼 代碼如下:

function doSomethingLater(fn, time) {
  var dfd = $.Deferred();
  setTimeout(function() {
    dfd.resolve(fn());
  }, time || 0);
  return dfd.promise();
}
var promise = doSomethingLater(function (){
  console.log( '已經(jīng)延遲執(zhí)行' );
}, 100);

自定義操作使用deferred接口

我們可以利用deferred接口,使得任意操作都可以用done()和fail()指定回調(diào)函數(shù)。

復(fù)制代碼 代碼如下:

Twitter = {
  search:function(query) {
    var dfr = $.Deferred();
    $.ajax({
     url:"http://search.twitter.com/search.json",
     data:{q:query},
     dataType:'jsonp',
     success:dfr.resolve
    });
    return dfr.promise();
  }
}

使用方法如下:

復(fù)制代碼 代碼如下:

Twitter.search('intridea').then(function(data) {
  alert(data.results[0].text);
});

deferred對(duì)象的另一個(gè)優(yōu)勢(shì)是可以附加多個(gè)回調(diào)函數(shù)。
復(fù)制代碼 代碼如下:

function doSomething(arg) {
  var dfr = $.Deferred();
  setTimeout(function() {
    dfr.reject("Sorry, something went wrong.");
  });
  return dfr;
}
doSomething("uh oh").done(function() {
  alert("Won't happen, we're erroring here!");
}).fail(function(message) {
  alert(message)
});

相關(guān)文章

最新評(píng)論