使用JQuery Deferred對象的then() 解決多個AJAX操作順序依賴的問題

來源:互聯網
上載者:User

之前的文章"javascript非同步代碼的回調地獄"中提到了編寫AJAX代碼經常遇到的3個問題,現在我們看下如何利用then()解決第2個問題:如果AJAX請求之間存在依賴關係,我們的代碼就會形成Pyramid of Doom(金字塔厄運)。比如我們要完成這樣一件事:有4個供Ajax訪問的url地址,需要先Ajax訪問第1個,在第1個訪問完成後,用拿到的返回資料作為參數再訪問第2個,第2個訪問完成後再第3個...以此到4個全部訪問完成。按照這樣的寫法,似乎會變成這樣:

$.ajax({      url: url1,      success: function(data){          $.ajax({              url: url2,              data: data,              success: function(data){                  $.ajax({                      //...                  });              }              });      }  });

1.Deferred.then()相當於Deferred.done()、Deferred.fail()、Deferred.progress()的合體,可以同時註冊3個狀態下的回呼函數。
function success(data){alert("success data = " + data);}function fail(data){alert("fail data = " + data);}function progress(data){alert("progress data = " + data);}var deferred = $.Deferred();// 一起註冊回調deferred.then(success, fail, progress);// 分別註冊回調deferred.done(success);deferred.fail(fail);deferred.progress(progress);deferred.notify("10%");deferred.resolve("ok");  
當然我們也可以像done()一樣,多次調用then()註冊回呼函數。then()雖然可以這麼使用,但是實際開發中一般不這麼用,因為沒有啥必要。JQuery1.8之前,這就是then()方法的作用。

2.Deferred.then()解決多個非同步作業之間有依賴的問題,這才是then()真正有意義的情境。JQuery1.8之後,then()取代了過時的pipe()方法。這種情境下,我們需要使用Deferred.then()返回的新Promise對象。上面的第一種使用方式,我們忽略了Deferred.then()的傳回值。

var deferred = $.Deferred();// 使用then()註冊一個resolved狀態的回呼函數,並返回一個過濾後的promise// 返回的filtered已經不是原來的Deferred或者Promise對象了var filtered = deferred.then(function( value ) {alert("trigger Deferred filter.value="+value);//5return value * 2;});// 用過濾後的Promise再次註冊回呼函數filtered.done(function( value ) {    alert("filtered value=" + value);//10}); deferred.resolve( 5 );

我們用deferred.then()註冊了一個完成狀態下的回呼函數,這個回呼函數得到的值是5;之後用filtered這個新的Promise註冊回呼函數,這個回呼函數中得到的值是10(第一個回呼函數的返回結果)。現在我們看下JQuery官方對then的解釋:

These filter functions can return a new value to be passed along to the promise's .done() or .fail() callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks. If the filter function used is null, or not specified, the promise will be resolved or rejected with the same values as the original.

我們知道deferred.resolve()、deferred.reject()、deferred.notify()可以指定參數值,這個參數會傳遞給相應狀態下的回呼函數。如果我們使用的是done()、fail()、progress()註冊的回呼函數,那麼某個狀態下的所有回呼函數得到的都是相同參數。但是如果我們使用了then()註冊回呼函數,那麼第一回呼函數的傳回值將作為第二個回呼函數的參數,同樣的第二個函數的傳回值是第三個回呼函數的參數。可以對比下面的2段代碼,體會下done()和then的差別。

var deferred = $.Deferred();// done()返回的仍然是原來的Deferred對象var done_ret = deferred.done(function(data){alert("data="+data);//5return 2 * data;});alert(deferred == done_ret);//truedone_ret.done(function(data){alert("data="+data);//5});deferred.resolve( 5 );


var deferred = $.Deferred();// then()返回的是一個新Promise對象//then註冊的回呼函數的傳回值將作為這個新Promise的參數var then_ret = deferred.then(function(data){alert("data="+data);//5return 2 * data;});alert(then_ret == deferred);//falsethen_ret.done(function(data){alert("data="+data);//10});deferred.resolve( 5 );

同樣地,Deferred.then也能夠實現rejected和pending狀態的回呼函數過濾。
var defer = $.Deferred();var filtered = defer.then( null, function( value ) {    return value * 3;  }); defer.reject( 6 );filtered.fail(function( value ) {  alert( "Value is ( 3*6 = ) 18: " + value );});


下面這段代碼可以實現chain tasks,解決非同步作業中回調難的問題。

var defered = $.Deferred();var promise1 = defered.then(function(data){alert(data);//return data+="1";});var promise2 = promise1.then(function(data){alert(data);//1return data+="2";});var promise3 = promise2.then(function(data){alert(data);//12return data+="3";});promise3.done(function(data){alert(data);//123});defered.resolve("");

正是由於then()這個特性,我們就可以上面複雜的AJAX嵌套改成如下形式:

var promise1 = $.ajax(url1);var promise2 = promise1.then(function(data){return $.ajax(url2, { "data": data });});var promise3 = promise2.then(function(data){return $.ajax(url3, { "data": data });});promise3.done(function(data){// data retrieved from url3});


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.