2012-01-10 112 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