0

一直在研究ajax()使用$.when我仍然不确定它是如何完全工作的,但这是我希望下面做的事情。

当用户每行添加城镇和国家时,它会转到 I get a response 中的 url,并将数组推送到循环.ajax()外可用。.each()

目前,您将在 jsbin内部看到,当button首先按下时,console.log 中的响应是,[]然后当我再次按下它时,地址就会显示出来。然后第三次按下将再次添加不应该发生的地址。

jQuery

var addresses,town;
var arrayLocation = [];

$('button').click(function(){
    addresses = function() {
        deferred = new $.Deferred();
        var arrayOfLines = $('#gps').val().split('\n');
        $.each(arrayOfLines, function(index, item) {
            town = item.split(',');
            $.ajax({
                url: 'http://maps.googleapis.com/maps/api/geocode/json?address='+town[0]+'&sensor=false',
                dataType: 'json',
                success: function (data) {
                    add = data.results[0].address_components[0].long_name;
                    lat = data.results[0].geometry.location.lat;
                    lng = data.results[0].geometry.location.lng;
                    arrayLocation.push("['"+add+"', "+lat+", "+lng+"]");
                    console.log("['"+add+"', "+lat+", "+lng+"]");
                }
            });
        });
        return arrayLocation;
    };
    $.when(addresses()).then(function(arrayLocation){
        console.log(arrayLocation);
    });
});
4

2 回答 2

5

你没有$.when正确使用。主要问题是该addresses函数返回一个裸数组。确实,将来当异步操作(一组 AJAX 调用)完成时会填充此数组,但从addresses' 调用者的角度来看,这是不可能知道的。因此,调用者绝对没有机会对正在完成的操作做出反应。

你通常会做的是将返回值返回$.ajax给调用者,有点像这样:

addresses = function() {
    return $.ajax({ ... });
};

然后调用者可以做

$.when(addresses()).then(function(result) { ... });

然而,在这个特定的例子中,这是不可能直接实现的,因为有多个 AJAX 调用正在进行,因此您需要某种方式将所有这些“组合”到一个包中。有多种方法可以做到这一点,所以这里还有一个你喜欢什么的问题。

一种解决方案是使用一系列 AJAX 承诺:

$('button').click(function(){
    var arrayLocation = [];
    addresses = function() {
        var promises = [];
        var arrayOfLines = $('#gps').val().split('\n');
        $.each(arrayOfLines, function(index, item) {
            town = item.split(',');
            promises.push($.ajax({
                url: 'http://maps.googleapis.com/...',
                dataType: 'json',
                success: function (data) {
                    add = data.results[0].address_components[0].long_name;
                    lat = data.results[0].geometry.location.lat;
                    lng = data.results[0].geometry.location.lng;
                    arrayLocation.push("['"+add+"', "+lat+", "+lng+"]");
                    console.log("['"+add+"', "+lat+", "+lng+"]");
                }
            }));
        });
        return promises;
    };

    $.when.apply($, addresses()).then(function(){
        console.log(arrayLocation);
    });
});

这里有几点需要注意:

  1. 返回一组独立的 Promise 意味着您不能$.when直接将它们提供给它们,因为该函数旨在接受多个单独的 Promise 而不是一个数组;你需要用来apply补偿。
  2. 我已经移动了arrayLocationclick 事件处理程序内部的声明,以便每次单击按钮时都会重置它。每次点击后再次添加结果的问题是由于这个数组没有被重置。
  3. 最终处理程序不接受任何参数。那是因为将传递的参数是代表单个 AJAX 请求的 jqXHR 对象,这并不是真正有用的。它不是arrayLocation通过闭包来捕获的,因为您独立地知道结果将存储在那里。
于 2013-11-08T12:25:02.467 回答
0

没有共享全局变量的略有不同的方法

$('button').click(function () {
    var addresses = function () {
        var arrayOfLines = $('#gps').val().split('\n'),
            arrayLocation = [];
        $.each(arrayOfLines, function (index, item) {
            var town = item.split(',');
            var xhr = $.ajax({
                url: 'http://maps.googleapis.com/maps/api/geocode/json?address=' + $.trim(town[0]) + '&sensor=false',
                dataType: 'json'
            });
            arrayLocation.push(xhr);
        });

        return $.when.apply($, arrayLocation).then(function () {
            return $.map(arguments, function (args) {
                if (!$.isArray(args[0].results) || args[0].results.length == 0) {
                    return undefined;
                }
                var data = args[0].results[0];
                var location = data.geometry.location;

                var add = data.address_components[0].long_name;
                var lat = location.lat;
                var lng = lng;

                return "['" + add + "', " + lat + ", " + lng + "]";
            });
        });

        return arrayLocation;
    };

    addresses().done(function (arrayLocation) {
        console.log(arrayLocation)
    })
});

演示:小提琴

于 2013-11-08T13:38:03.057 回答