2012-01-10 110 views
2

我試圖在OO風格中使用Javascript,並且一種方法需要進行遠程調用以獲取一些數據,以便網頁可以使用它。我創建了一個Javascript類來封裝數據檢索,所以我可以在其他地方重複使用的邏輯,就像這樣:從jQuery Ajax方法返回值

AddressRetriever = function() { 
    AddressRetriever.prototype.find = function(zip) { 
     var addressList = []; 
     $.ajax({ 
      /* setup stuff */ 
      success: function(response) { 
       var data = $.parseJSON(response.value); 
       for (var i = 0; i < data.length; i++) { 
        var city = data[i].City; // "City" column of DataTable 
        var state = data[i].State; // "State" column of DataTable 
        var address = new PostalAddress(postalCode, city, state); // This is a custom JavaScript class with simple getters, a DTO basically. 
        addressList.push(address); 
       } 
      } 
     }); 
     return addressList; 
    } 
} 

網頁本身調用此類似如下:

$('#txtZip').blur(function() { 
    var retriever = new AddressRetriever(); 
    var addresses = retriever.find($(this).val()); 

    if (addresses.length > 0) { 
     $('#txtCity').val(addresses[0].getCity()); 
     $('#txtState').val(addresses[0].getState()); 
    } 
}); 

的問題是有時addresses是莫名其妙的空(即長度= 0)。在Firebug中,XHR選項卡顯示一個響應,返回期望的數據,如果我在成功方法中設置了警報長度是正確的,但在該方法外面,當我嘗試返回值時,它有時(但並非總是)爲空,我的文本框沒有被填充。有時它顯示爲空,但文本框得到正確填充無論如何。

我知道我可以通過擺脫單獨的類並將整個ajax調用填充到事件處理程序中來完成此操作,但是我正在尋找一種方法來正確執行此操作,以便可以在必要時重用該功能。有什麼想法嗎?

+1

可能重複[無法從jQuery Ajax調用獲取正確的返回值](http://stackoverflow.com/questions/3537434/cant -get-correct-return-value-from -a-jquery-ajax-call) – 2012-01-10 19:40:49

+0

聽起來你需要在成功塊中包含一個「error:」處理程序並返回addressList。另外,因爲它是異步的。調用時,可以在ajax調用完成之前發生「返回地址列表」。 – 2012-01-10 19:50:26

+0

[JavaScript異步返回值/賦值與jQuery]的可能重複(http://stackoverflow.com/questions/7779697/javascript-asynchronous-return-value-assignment-with-jquery) – 2012-01-10 19:52:56

回答

2

簡而言之,你不能像你試圖用異步ajax調用來做到這一點。

Ajax方法通常運行異步。因此,當ajax函數調用本身返回時(您的代碼中有return addressList),實際的ajax網絡尚未完成,結果尚不清楚。

相反,您需要重新修改代碼流的工作方式,並僅在成功處理函數或您從成功處理程序調用的函數中處理ajax調用的結果。只有在調用成功處理程序時纔會完成ajax聯網並提供結果。

簡而言之,在使用異步ajax調用時,不能執行正常的過程編程。你必須改變你的代碼結構和流程的方式。它使事情變得複雜,但用戶體驗對使用異步ajax調用的好處是巨大的(瀏覽器在網絡操作期間不鎖定)。

這裏是你如何調整你的代碼,同時仍然使用一個回調函數保持AddressRetriever.find()方法很普通:

AddressRetriever = function() { 
    AddressRetriever.prototype.find = function(zip, callback) { 
     $.ajax({ 
      /* setup stuff */ 
      success: function(response) { 
       var addressList = []; 
       var data = $.parseJSON(response.value); 
       for (var i = 0; i < data.length; i++) { 
        var city = data[i].City; // "City" column of DataTable 
        var state = data[i].State; // "State" column of DataTable 
        var address = new PostalAddress(postalCode, city, state); // This is a custom JavaScript class with simple getters, a DTO basically. 
        addressList.push(address); 
       } 
       callback(addressList); 
      } 
     }); 
    } 
} 

$('#txtZip').blur(function() { 
    var retriever = new AddressRetriever(); 
    retriever.find($(this).val(), function(addresses) { 
     if (addresses.length > 0) { 
      $('#txtCity').val(addresses[0].getCity()); 
      $('#txtState').val(addresses[0].getState()); 
     } 
    }); 

}); 
+0

好吧,所以它看起來像我需要包括回調,然後我可以保持我的代碼結構正確,同時仍然可以使用Ajax方法。 – 2012-01-10 19:58:15

0

不是莫名可言,列表不會被填補,直到時間的不確定量未來。

規範的方法是在你的成功處理程序中完成工作,也許通過傳遞你自己的回調。您也可以使用jQuery's .when

0

AJAX調用是異步的,這意味着它們不會以正常流程運行。當您執行

if (addresses.length > 0) { 

addresses其實,空的,因爲程序沒有等到AJAX調用來完成。

2
AddressRetriever = function() { 
    AddressRetriever.prototype.find = function(zip) { 
     var addressList = []; 
     $.ajax({ 
      /* setup stuff */ 
      success: function(response) { 
       var data = $.parseJSON(response.value); 
       for (var i = 0; i < data.length; i++) { 
        var city = data[i].City; // "City" column of DataTable 
        var state = data[i].State; // "State" column of DataTable 
        var address = new PostalAddress(postalCode, city, state); // This is a custom JavaScript class with simple getters, a DTO basically. 
        addressList.push(address); 
        processAddresss(addressList); 
       } 
      } 
     }); 
    } 
} 

function processAddresss(addressList){ 
    if (addresses.length > 0) { 
     $('#txtCity').val(addresses[0].getCity()); 
     $('#txtState').val(addresses[0].getState()); 
    } 
} 

或者如果你不想進行另一個函數調用,使ajax調用同步。現在,它是在數據被推入數組之前返回數組

+1

該實現使'.find()'硬連線到一個特定的網頁和該頁面上的一個特定對象。這大大降低了AddressRetriever對象的實用性。使用回調函數可以使數據對象獨立於HTML,並讓數據用於許多不同的事情和大量不同的頁面設計等等。 – jfriend00 2012-01-10 19:49:49

+0

謝謝,挺對.. 還在學! – redDevil 2012-01-10 20:18:12