偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

在jQuery 1.5中使用deferred對(duì)象

開(kāi)發(fā) 前端
jQuery1.5中新增的Deferreds對(duì)象,可以將任務(wù)完成的處理方式與任務(wù)本身解耦合。這在JavaScript社區(qū)沒(méi)什么新意,因?yàn)镸ochikit和Dojo兩個(gè)JS框架已經(jīng)實(shí)現(xiàn)了這個(gè)特性很長(zhǎng)一段時(shí)間了。

Deferred是jQuery1.5新增的一個(gè)特性,很多人把它翻譯成 “異步隊(duì)列”,我覺(jué)得比較靠譜,畢竟和“延遲”沒(méi)啥關(guān)系,不過(guò)這篇文章中我還采用deferred這個(gè)單詞。 這篇文章在jQuery1.5發(fā)布博客中提到,也是目前介紹deferred比較經(jīng)典和深入的文章。鑒于目前中文資料比較少,特別翻譯出來(lái)供大家學(xué)習(xí)參考。

jQuery1.5中新增的Deferreds對(duì)象,可以將任務(wù)完成的處理方式與任務(wù)本身解耦合。這在JavaScript社區(qū)沒(méi)什么新意,因?yàn)镸ochikit和Dojo兩個(gè)JS框架已經(jīng)實(shí)現(xiàn)了這個(gè)特性很長(zhǎng)一段時(shí)間了。但是隨著Julian Aubourg對(duì)jQuery1.5中AJAX模塊的重寫(xiě),deferreds理所當(dāng)然成為了內(nèi)部的實(shí)現(xiàn)邏輯。使用deferreds對(duì)象,多個(gè)回調(diào)函數(shù)可以被綁定在任務(wù)完成時(shí)執(zhí)行,甚至可以在任務(wù)完成后綁定這些回調(diào)函數(shù)。這些任務(wù)可以是異步的,也可以是同步的。

更重要的是,deferreds已經(jīng)作為$.ajax()的內(nèi)部實(shí)現(xiàn),所以你可以在調(diào)用AJAX時(shí)自動(dòng)獲取deferreds帶來(lái)的遍歷。比如我們可以這樣綁定回調(diào)函數(shù):

  1. // $.get, 異步的AJAX請(qǐng)求  
  2. var req = $.get('foo.htm').success(function (response) {  
  3.     // AJAX成功后的處理函數(shù)  
  4. }).error(function () {  
  5.     // AJAX失敗后處理函數(shù)  
  6. });  
  7.    
  8. // 這個(gè)函數(shù)有可能在AJAX結(jié)束前調(diào)用  
  9. doSomethingAwesome();  
  10.    
  11. // 添加另外一個(gè)AJAX回調(diào)函數(shù),此時(shí)AJAX或許已經(jīng)結(jié)束,或許還沒(méi)有結(jié)束  
  12. // 由于$.ajax內(nèi)置了deferred的支持,所以我們可以這樣寫(xiě)  
  13. req.success(function (response) {  
  14.     // 這個(gè)函數(shù)會(huì)在AJAX結(jié)束后被調(diào)用,或者立即被調(diào)用如果AJAX已經(jīng)結(jié)束  
  15. }); 

我們不再被限制到只有一個(gè)成功,失敗或者完成的回調(diào)函數(shù)了。相反這些隨時(shí)被添加的回調(diào)函數(shù)被放置在一個(gè)先進(jìn)先出的隊(duì)列中。

從上面例子看出,回調(diào)函數(shù)可以被附加到AJAX請(qǐng)求中(任何可觀(guān)察的任務(wù)observable task),甚至在AJAX請(qǐng)求已經(jīng)結(jié)束。對(duì)于代碼的組織是很好的,我們?cè)僖膊挥脤?xiě)很長(zhǎng)的回調(diào)函數(shù)了。這就像$.queue()遇到了pub/sub(發(fā)布訂閱機(jī)制,一般用在基于事件處理的模型中).

更深入一些,想象這樣一個(gè)場(chǎng)景,在一些并發(fā)的AJAX請(qǐng)求全部結(jié)束之后執(zhí)行一個(gè)回調(diào)函數(shù)。我可以方便的通過(guò)jQuery的函數(shù)$.when()來(lái)完成:

  1. function doAjax() {  
  2.     return $.get('foo.htm');  
  3. }  
  4.    
  5. function doMoreAjax() {  
  6.     return $.get('bar.htm');  
  7. }  
  8.    
  9. $.when(doAjax(), doMoreAjax()).then(function () {  
  10.     console.log('I fire once BOTH ajax requests have completed!');  
  11. }).fail(function () {  
  12.     console.log('I fire if one or more requests failed.');  
  13. }); 

在jsFiddle中打開(kāi)示例 http://jsfiddle.net/ehynds/Mrqf8/

上面的示例能夠正常運(yùn)行,這要?dú)w功于每個(gè)jQuery的AJAX方法返回值都包含一個(gè)promise函數(shù),用來(lái)跟蹤異步請(qǐng)求。Promise函數(shù)的返回值是deferred對(duì)象的一個(gè)只讀視圖。(The promise is a read-only view into the result of the task.)Deferreds通過(guò)檢測(cè)對(duì)象中是否存在promise()函數(shù)來(lái)判斷當(dāng)前對(duì)象是否可觀(guān)察。$.when()會(huì)等待所有的AJAX請(qǐng)求結(jié)束,然后調(diào)用通過(guò) .then(), .fail()注冊(cè)的回調(diào)函數(shù)(具體調(diào)用哪些回調(diào)函數(shù)取決于任務(wù)的結(jié)束狀態(tài))。這些回調(diào)函數(shù)會(huì)按照他們的注冊(cè)順序執(zhí)行。

更好的是,$.when()接受函數(shù)或者函數(shù)的數(shù)組為參數(shù)(譯者注:這點(diǎn)不大對(duì),$.when接受一個(gè)或多個(gè)deferred對(duì)象,或者原生的JS對(duì)象。注意不能以函數(shù)數(shù)組為參數(shù)),這樣你就可以隨意組合這些異步任務(wù)。

$.ajax()返回一個(gè)對(duì)象,這個(gè)對(duì)象關(guān)聯(lián)一些deferred函數(shù),比如promise(), then(), success(), error()。然而你不能操作原始的deferred對(duì)象,只有promise()函數(shù)(譯者注:還記得剛才提到的promise是只讀視圖),以及可以檢測(cè)deferred狀態(tài)的isRejected() 以及isResolved()函數(shù)。

但是為什么不返回deferred對(duì)象呢?如果返回了完整的deferred對(duì)象,那么我們就擁有更多的控制,或許可以隨意的觸發(fā)(譯者注:我把resolve翻譯成觸發(fā),就是觸發(fā)所有注冊(cè)到deferred對(duì)象上的回調(diào)函數(shù))deferred對(duì)象,從而導(dǎo)致所有回調(diào)函數(shù)在AJAX請(qǐng)求結(jié)束之前執(zhí)行。因此,為了避免不期望的觸發(fā)deferred的風(fēng)險(xiǎn),我們應(yīng)該只返回dfd.promise().(Therefore, to avoid potentially breaking the whole paradigm, only return the dfd.promise().)(譯者注:如果你很迷惑上面幾段話(huà)的確切意思,沒(méi)關(guān)系,我隨后會(huì)寫(xiě)一篇文章深層次分析其中原因:http:/cnblogs.com/sanshi/)

注冊(cè)回調(diào)函數(shù)(Registering Callbacks)

上面的例子中,我們使用then(), success(), fail()方法來(lái)注冊(cè)回調(diào)函數(shù),其實(shí)還有更多的方法可以使用,特別在處理AJAX請(qǐng)求時(shí)。具體使用哪種方式取決于你對(duì)結(jié)果狀態(tài)的關(guān)注。

所有deferred對(duì)象都有的函數(shù) (AJAX, $.when 或者手工創(chuàng)建的deferred對(duì)象):

  1. .then( doneCallbacks, failedCallbacks )  
  2. .done( doneCallbacks )  
  3. .fail( failCallbacks ) 

AJAX對(duì)象包含3個(gè)額外的方法,其中兩個(gè)會(huì)映射到上面提到的方法。這些方法主要是為了兼容以前的代碼:

  1. // "success" 和 "error" 會(huì)分別映射到 "done" and "fail" 兩個(gè)方法  
  2. .success( doneCallbacks )  
  3. .error( failCallbacks ) 

你也可以注冊(cè)一個(gè)complete的回調(diào)函數(shù),它會(huì)在請(qǐng)求結(jié)束后調(diào)用,而不管這個(gè)請(qǐng)求是成功或者失敗。不像success或者error函數(shù),complete函數(shù)其實(shí)是一個(gè)單獨(dú)的deferred對(duì)象的done函數(shù)別名。這個(gè)在$.ajax()內(nèi)部創(chuàng)建的deferred對(duì)象,會(huì)在AJAX結(jié)束后觸發(fā)回調(diào)函數(shù)(resolve)。

  1. .complete( completeCallbacks ) 

因此,下面的3個(gè)例子是等價(jià)的(在AJAX的上下文中,success看起來(lái)比done函數(shù)會(huì)舒服點(diǎn),對(duì)么?)(譯者注:其實(shí)是因?yàn)槲覀兪煜ひ郧暗腁JAX調(diào)用方式,先入為主罷了,或者叫思維定勢(shì)):

  1. $.get("/foo/").done( fn );  
  2. // 等價(jià)于:  
  3. $.get("/foo/").success( fn );  
  4. // 等價(jià)于:  
  5. $.get("/foo/", fn ); 

創(chuàng)建自己的deferred對(duì)象(Creating your own Deferred)

我們知道$.ajax和$.when在內(nèi)部實(shí)現(xiàn)了deferred接口,不過(guò)我們也可以手工創(chuàng)建deferred對(duì)象:

  1. function getData() {  
  2.     return $.get('/foo/');  
  3. }  
  4.    
  5. function showDiv() {  
  6.     var dfd = $.Deferred();  
  7.     $('#foo').fadeIn(1000, dfd.resolve);  
  8.     return dfd.promise();  
  9. }  
  10.    
  11. $.when(getData(), showDiv()).then(function (ajaxResult) {  
  12.     console.log('The animation AND the AJAX request are both done!');  
  13.     // 'ajaxResult'是服務(wù)器端返回(譯者注:也就是getData中AJAX的結(jié)果)  
  14. }); 

在jsFiddle中打開(kāi)示例 http://jsfiddle.net/ehynds/JSw5y/

在showDiv()中,我們創(chuàng)建了一個(gè)deferred對(duì)象,執(zhí)行了一段動(dòng)畫(huà),然后返回promise。這個(gè)deferred對(duì)象會(huì)在fadeIn()結(jié)束后被觸發(fā)(resolved)。在這個(gè)promise返回和deferred對(duì)象(注意:這里的deferred指的是$.when創(chuàng)建的對(duì)象,而非showDiv()返回的對(duì)象)觸發(fā)的中間,一個(gè)then()回調(diào)函數(shù)會(huì)被注冊(cè)。這個(gè)回調(diào)函數(shù)會(huì)在兩個(gè)異步的任務(wù)全部結(jié)束后執(zhí)行。

getData()返回一個(gè)對(duì)象(譯者注:其實(shí)是jQuery封裝的XMLHttpRequest對(duì)象)擁有promise方法,這就允許$.when()監(jiān)視本次AJAX請(qǐng)求的結(jié)束。The manually steps we took to return a promise in showDiv() is handled for us internally by $.ajax() and $.when().

1/15/2011: Julian在評(píng)論中指出,上面的語(yǔ)法可以被簡(jiǎn)化為$.Deferred(fn).promise()。因此下面的兩端代碼是等價(jià)的:

  1. function showDiv() {  
  2.     var dfd = $.Deferred();  
  3.     $('#foo').fadeIn(1000, dfd.resolve);  
  4.     return dfd.promise();  
  5. }  
  6. // 等價(jià)于:  
  7. function showDiv() {  
  8.     return $.Deferred(function (dfd) {  
  9.         $('#foo').fadeIn(1000, dfd.resolve);  
  10.     }).promise();  

為自定義的deferred對(duì)象添加回調(diào)函數(shù)(Defer your Deferreds)

我們可以更進(jìn)一步,為getData()和showDiv()分別注冊(cè)回調(diào)函數(shù),如同我們?cè)?.then()中注冊(cè)回調(diào)函數(shù)一樣。(譯者注:下面的段落內(nèi)容重復(fù),說(shuō)的都是一個(gè)意思,就不翻譯了,看代碼吧)

  1. function getData() {  
  2.     return $.get('/foo/').success(function () {  
  3.         console.log('Fires after the AJAX request succeeds');  
  4.     });  
  5. }  
  6.    
  7. function showDiv() {  
  8.     return $.Deferred(function (dfd) {  
  9.         // 譯者注:這段代碼是原文沒(méi)有的,但是在jsFiddle中出現(xiàn)。  
  10.         // 我覺(jué)得這是作者的原意,為自定義的deferred函數(shù)注冊(cè)回調(diào)函數(shù)  
  11.         dfd.done(function () {  
  12.             console.log('Fires after the animation succeeds');  
  13.         });  
  14.         $('#foo').fadeIn(1000, dfd.resolve);  
  15.     }).promise();  
  16. }  
  17.    
  18. $.when(getData(), showDiv()).then(function (ajaxResult) {  
  19.     console.log('Fires after BOTH showDiv() AND the AJAX request succeed!');  
  20.     // 'ajaxResult'是服務(wù)器返回結(jié)果  
  21. }); 

在jsFiddle中打開(kāi)示例 http://jsfiddle.net/ehynds/W3cQc/

鏈?zhǔn)酱a(Chaining Hotness)

Deferred的回調(diào)函數(shù)可以鏈?zhǔn)秸{(diào)用,只要函數(shù)返回的是deferred對(duì)象(譯者注:dfd.promise()返回的是只讀的deferred對(duì)象)。這是一個(gè)實(shí)際的代碼 (via @ajpiano!)

  1. function saveContact(row) {  
  2.     var form = $.tmpl(templates["contact-form"]),  
  3.         valid = true,  
  4.         messages = [],  
  5.         dfd = $.Deferred();  
  6.    
  7. /*  
  8.  *   這里方式客戶(hù)端驗(yàn)證代碼  
  9.  */ 
  10.    
  11.     if (!valid) {  
  12.         dfd.resolve({  
  13.             success: false,  
  14.             errors: messages  
  15.         });  
  16.     } else {  
  17.         form.ajaxSubmit({  
  18.             dataType: "json",  
  19.             success: dfd.resolve,  
  20.             error: dfd.reject  
  21.         });  
  22.     }  
  23.    
  24.     return dfd.promise();  
  25. };  
  26.    
  27. saveContact(row).then(function (response) {  
  28.     if (response.success) {  
  29.         // 客戶(hù)端驗(yàn)證通過(guò),并且保存數(shù)據(jù)成功  
  30.     } else {  
  31.         // 客戶(hù)端驗(yàn)證失敗  
  32.         // 輸出錯(cuò)誤信息  
  33.     }  
  34. }).fail(function (err) {  
  35.     // AJAX請(qǐng)求失敗  
  36. }); 

saveContact()函數(shù)首先驗(yàn)證表單數(shù)據(jù)的有效性,然后把有效性狀態(tài)保存在變量valid中。如果驗(yàn)證失敗,直接deferred會(huì)被觸發(fā)(把一個(gè)包含success狀態(tài)碼和錯(cuò)誤信息的JS對(duì)象作為參數(shù)傳遞給回調(diào)函數(shù))。如果驗(yàn)證通過(guò),則向服務(wù)器提交數(shù)據(jù),在AJAX成功完成后觸發(fā)deferred對(duì)象。fail()會(huì)處理404, 500等可以阻止AJAX請(qǐng)求成功完成的HTTP狀態(tài)碼。

不可觀(guān)察的任務(wù)(Non-observable Tasks)

Deferreds對(duì)于解耦任務(wù)與任務(wù)處理函數(shù)時(shí)非常有用,而不管是異步任務(wù)或者同步任務(wù)。一個(gè)任務(wù)可能會(huì)返回promise,但也可以返回字符串,對(duì)象或者其他類(lèi)型。

在這個(gè)例子中,當(dāng)“Lanch Application”鏈接被***點(diǎn)擊時(shí),一個(gè)AJAX請(qǐng)求會(huì)發(fā)送到服務(wù)器并返回當(dāng)前時(shí)間戳。然后這個(gè)時(shí)間戳?xí)槐4娴竭@個(gè)鏈接的data緩存中。當(dāng)這個(gè)鏈接再次被點(diǎn)擊時(shí),只是簡(jiǎn)單的從緩存中取出這個(gè)時(shí)間戳返回,而不會(huì)發(fā)出AJAX請(qǐng)求。

  1. function startTask(element) {  
  2.     var timestamp = $.data(element, 'timestamp');  
  3.    
  4.     if (timestamp) {  
  5.         return timestamp;  
  6.     } else {  
  7.         return $.get('/start-task/').success(function (timestamp) {  
  8.             $.data(element, 'timestamp', timestamp);  
  9.         });  
  10.     }  
  11. }  
  12.    
  13. $('#launchApplication').bind('click'function (event) {  
  14.     event.preventDefault();  
  15.    
  16.     $.when(startTask(this)).done(function (timestamp) {  
  17.         $('#status').html('<p>You first started this task on: ' + timestamp + '</p>');  
  18.     });  
  19.    
  20.     loadApplication();  
  21. }); 

當(dāng)$.when()發(fā)現(xiàn)它的***個(gè)參數(shù)沒(méi)有promise函數(shù)(因此不可觀(guān)察),它就會(huì)創(chuàng)建一個(gè)新的deferred對(duì)象,觸發(fā)deferred對(duì)象,并返回promise只讀對(duì)象。因此,任意不可觀(guān)察的任務(wù)也能傳遞到$.when()中。

需要注意的一個(gè)問(wèn)題是,如果一個(gè)對(duì)象自身?yè)碛衟romise函數(shù),則這個(gè)對(duì)象將不能作為deferred對(duì)象。jQuery判斷一個(gè)對(duì)象是否deferred,是通過(guò)查看它是否有promise函數(shù)來(lái)決定的,但是jQuery并不會(huì)檢查這個(gè)promise是否真的返回一個(gè)可用的對(duì)象。因此下面的代碼將會(huì)出錯(cuò):

  1. var obj = {  
  2.     promise: function () {  
  3.         // do something  
  4.     }  
  5. };  
  6.    
  7. $.when(obj).then(fn); 

結(jié)論(Conclusion)

Deferreds提出了一種新的健壯的方式來(lái)處理異步任務(wù)。和傳統(tǒng)的將代碼組織到一個(gè)回調(diào)函數(shù)中不同,新的deferred對(duì)象允許我們?cè)谌魏螘r(shí)候(甚至在任務(wù)結(jié)束后)綁定多個(gè)回調(diào)函數(shù),而這些回調(diào)函數(shù)會(huì)以先進(jìn)先出的方式被調(diào)用。這篇文章中的信息可能比較難以消化,不過(guò)一旦你掌握了deferred對(duì)象的使用,你會(huì)發(fā)現(xiàn)組織異步執(zhí)行的代碼將會(huì)非常容易。
 

原文鏈接:http://www.cnblogs.com/sanshi/archive/2011/03/10/1980195.html

【編輯推薦】

  1. jQuery異步調(diào)用頁(yè)面后臺(tái)實(shí)例分析
  2. jQuery 1.5正式版發(fā)布 五大變化引人注目
  3. 18個(gè)***最給力的jQuery教程分享
  4. jQuery實(shí)現(xiàn)表格數(shù)據(jù)的動(dòng)態(tài)添加與統(tǒng)計(jì)
  5. jQuery1.5新特征之插件機(jī)制的救贖
責(zé)任編輯:陳貽新 來(lái)源: 博客園
相關(guān)推薦

2011-08-22 16:19:58

jQuery

2018-11-26 09:20:26

GrailsjQueryDataTables

2015-07-16 14:24:44

jQueryAlpha

2010-04-14 10:12:07

Oracle數(shù)據(jù)庫(kù)

2013-12-13 17:21:14

Lua腳本語(yǔ)言

2009-06-25 16:49:24

Hibernate

2023-11-17 12:04:39

GORM并發(fā)

2023-04-12 15:25:09

Bytrace鴻蒙

2011-06-08 16:56:37

VS2008 Qt

2011-10-26 10:12:53

Sencha Touc布局

2023-12-15 15:03:54

.NETAutoMapper對(duì)象映射工具

2011-06-15 10:08:01

Qt CVS

2017-04-05 13:17:26

LinuxShellvi

2010-04-29 17:51:40

Unix工具

2023-07-04 16:36:03

Linuxcd 命令

2023-07-23 19:26:18

Linuxcat 命令

2021-03-22 08:45:30

異步編程Java

2023-08-12 15:05:26

Linuxcp 命令

2012-04-19 12:58:26

TitaniumJSS

2009-06-16 09:06:37

JavaMailJSP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)