JSON请求在jQuery中无法正常工作每个函数

时间:2017-06-19 23:43:45

标签: javascript jquery json api foreach

如果为包含类.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,用于包含类event的每个div。除非用户更改了地址,否则这些值将保持不变,此时将通过JSON请求再次检索它们。

然后应提交表格。

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

2 个答案:

答案 0 :(得分:2)

$.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)将变量声明为本地变量的习惯。

答案 1 :(得分:1)

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

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

这是代码(不是测试)和评论:

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