【问题标题】:JSON request not working correctly in jQuery Each functionJSON请求在jQuery每个函数中无法正常工作
【发布时间】:2017-06-19 23:43:44
【问题描述】:

如果包含 .event 类的每个 div 的值已更改,我将使用下面的代码来检索给定位置的纬度和经度。

我遇到的问题是这段代码只出现了两个结果:

  • 从一个 JSON 请求返回的值用于每个 latlon 变量
  • 变量 latlon 保持完全相同,就好像它们保持不变,因此 JSON 值不会被替换。

下面是我正在使用的代码:

    $(".button").click(function(){

            data = "";
            $(".event").each(function(){

                original = $(this).find(".address").data("original");
                location = $(this).find(".address").html();
                lat = $(this).find(".lat").html();
                lon = $(this).find(".lon").html();

                if (original !== location) {

                    $.getJSON( "http://nominatim.openstreetmap.org/search?q="+location+"&format=json&polygon=1&addressdetails=1", function(result) {
                        lat = result[0].lat;
                        lon = result[0].lon;
                    });

                }

                data = data + randomNumber() + ": " + lat + " " + lon + ",";

            });

            $(".data").val(data);
            $(".form").submit();

    });

变量data 将包含latlon,每个div 包含event 类。除非用户更改了地址,否则这些值将保持不变,此时将通过 JSON 请求再次检索它们。

然后应该提交表单。

我该如何解决这个问题?谢谢

【问题讨论】:

  • $.getJSON 是异步的。你在回调函数执行之前设置data

标签: javascript jquery json api foreach


【解决方案1】:

$.getJSON是异步的,不能在回调函数外引用结果。而且您不想在所有 AJAX 请求完成之前提交表单。

$.getJSON() 返回一个Deferred。您可以将它们全部组成一个数组,然后使用$.when() 等待它们。

$(".button").click(function() {

  var promises = [];
  var data = "";
  $(".event").each(function() {

    var original = $(this).find(".address").data("original");
    var location = $(this).find(".address").html();
    var lat = $(this).find(".lat").html();
    var lon = $(this).find(".lon").html();

    if (original !== location) {
      promises.push($.getJSON("http://nominatim.openstreetmap.org/search?q=" + location + "&format=json&polygon=1&addressdetails=1", function(result) {
        var lat = result[0].lat;
        var lon = result[0].lon;
        data += randomNumber() + ": " + lat + " " + lon + ",";
      }));

    } else {
      data += randomNumber() + ": " + lat + " " + lon + ",";
    }

  });
  $.when.apply($, promises).done(function() {

    $(".data").val(data);
    $(".form").submit();
  });

});

请注意,data 中值的顺序是不可预测的,因为 AJAX 请求的返回顺序不一定与它们发送的顺序相同。

您还应该养成使用 var(或 ES6 中的 let)将变量声明为本地变量的习惯。

【讨论】:

  • 非常感谢您!还有var lat/lon在所需的JSON请求下,因为它已经被声明为变量?由于某些事件具有相同的地址,该代码有点错误,所以我不得不删除它。
  • 除非您确实需要,否则最好避免在不同函数之间共享变量。 AJAX 回调函数无需使用与迭代函数相同的lat/lon 变量。
【解决方案2】:

我认为你应该同时调用$.getJSON,然后在得到所有结果的同时处理所有结果。

如果某个位置不需要$.getJSON,您可以创建一个立即解析延迟/承诺来模拟异步调用。这样我们就可以处理相同类型的结果(jQuery Promise Object)。

这是代码(不是测试)和 cmets:

$(".button").click(function() {
    // data = "";
    // unnecessary

    // $(".event").each(function() {
    // use map to get promise objects for every ".event"
    var promises = $(".event").map(function() {
        original = $(this).find(".address").data("original");
        location = $(this).find(".address").html();
        // lat = $(this).find(".lat").html();
        // lon = $(this).find(".lon").html();
        // not need here

        if (original !== location) {
            return $.getJSON("http://nominatim.openstreetmap.org/search?q=" + location + "&format=json&polygon=1&addressdetails=1", function(result) {
                lat = result[0].lat;
                lon = result[0].lon;
            });
        } else {
            // make value type same as json, it's a array of { lat, lon }
            return $.Deferred().resolve([{
                lat: $(this).find(".lat").html(),
                lon: $(this).find(".lon").html()
            }]).promise();
        }

        // data = data + randomNumber() + ": " + lat + " " + lon + ",";
        // do it later, after all promise resolved.
    });

    $.when.apply(null, promises)
        .done(function() {
            // convert arguments to a array
            var args = [].slice.apply(arguments);
            data = args
                .map(function(models) {
                    // convert each model to a string
                    var model = models[0];
                    return randomNumber() + ": " + model.lat + " " + lon;
                })
                // join each part with separator ','
                .join(",");

            // while got data, deal with it
            $(".data").val(data);
            $(".form").submit();
        });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-26
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 2014-04-21
    • 2018-12-03
    • 2014-06-08
    相关资源
    最近更新 更多