【问题标题】:Returning a value from a jQuery Ajax method从 jQuery Ajax 方法返回一个值
【发布时间】:2012-02-07 05:31:24
【问题描述】:

我正在尝试以 OO 风格使用 Javascript,一种方法需要进行远程调用以获取一些数据,以便网页可以使用它。我创建了一个 Javascript 类来封装数据检索,因此我可以在其他地方重用逻辑,如下所示:

 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 调用填充到事件处理程序中来做到这一点,但我正在寻找一种方法来正确地做到这一点,以便在必要时可以重用该函数。有什么想法吗?

【问题讨论】:

标签: javascript jquery ajax


【解决方案1】:

简而言之,您不能像尝试通过异步 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());
        }
    });

});

【讨论】:

  • 好吧,看来我需要包含回调,然后我可以保持我的代码结构正确,同时仍然能够使用 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 调用同步。现在,它在数据被推入数组之前返回数组

【讨论】:

  • 此实现使.find() 硬连线到一个特定网页和该页面上的一个特定对象。这大大降低了 AddressRetriever 对象的实用性。使用回调函数可以让数据对象保持独立于 HTML,并让数据用于许多不同的事物和许多不同的页面设计等......
【解决方案3】:

一点也不莫名其妙,直到未来一段不确定的时间才会填满。

规范的方法是在您的成功处理程序中完成工作,也许通过传入您自己的回调。您也可以使用jQuery's .when

【讨论】:

    【解决方案4】:

    AJAX 调用是异步的,这意味着它们不会按照程序的常规流程运行。当你执行

    if (addresses.length > 0) { 
    

    addresses 实际上是空的,因为程序没有等待 AJAX 调用完成。

    【讨论】:

      猜你喜欢
      • 2012-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2010-12-26
      • 2016-01-03
      • 2010-11-30
      相关资源
      最近更新 更多