【问题标题】:jQuery using .when and pushing an arrayjQuery 使用 .when 并推送数组
【发布时间】:2013-11-20 10:48:02
【问题描述】:

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

当用户每行添加城镇和国家/地区时,它会转到 .ajax() 中的 url,我会收到响应,它会将数组推送到 .each() 循环之外可用。

目前您会在 here at 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);
    });
});

【问题讨论】:

标签: javascript jquery ajax asynchronous .when


【解决方案1】:

您没有正确使用$.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. 我已将arrayLocation 的声明移动到单击事件处理程序中,以便每次单击按钮时都会重置它。每次点击后重新添加结果的问题是由于这个数组没有被重置。
  3. 最终处理程序不接受任何参数。那是因为将传递的参数是代表单个 AJAX 请求的 jqXHR 对象,这并不是真正有用的。相反,它通过闭包捕获arrayLocation,因为您独立地知道结果将存储在那里。

【讨论】:

  • 呃,我的答案输入到一半,我就看到了。太快了!很好的答案。
【解决方案2】:

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

$('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)
    })
});

演示:Fiddle

【讨论】:

    猜你喜欢
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多