从jQuery Ajax方法返回一个值

时间:2012-01-10 19:38:32

标签: javascript jquery ajax

我正在尝试以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选项卡显示带有预期数据的响应,如果我在success方法中设置了一个警告长度是正确的,但在我尝试返回该值时,该方法之外,有时(但并非总是如此) )空,我的文本框不会填充。有时候它会显示为空,但文本框无论如何都会正确填充。

我知道我可以通过删除单独的类并将整个ajax调用填充到事件处理程序中来完成此操作,但我正在寻找一种方法来正确执行此操作,以便在必要时可以重用该函数。有什么想法吗?

4 个答案:

答案 0 :(得分: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());
        }
    });

});

答案 1 :(得分: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调用同步。现在,它在数据被推入数组之前返回数组

答案 2 :(得分:0)

根本没有莫名其妙,该名单将在未来不确定的时间内填补。

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

答案 3 :(得分:0)

AJAX调用是异步的,这意味着它们不能与程序的常规流程一起运行。执行时

if (addresses.length > 0) { 

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