在ajax json调用之间添加延迟

时间:2016-12-19 03:09:55

标签: javascript html json ajax

如果这不是正确的问题,请提前抱歉,请告诉我如何改进我的问题:)

基本上我有一个json文件,我想从(名称,地址等)中提取数据,以便使用Google Maps API函数将它们绘制为标记。这是我使用的当前ajax函数:

$.ajax({
    url: 'directory.json',
    dataType: 'json',
    type: 'get',
    cache: 'false',
    success: function(data) {
        $(data.group).each(function(index, person) {
        if (typeof person.Address != "undefined") {
            geocodeAddress(geocoder, map, person);
        }
    });
  }
});

但是,这是同时为所有800多个目录条目调用geocodeAddress函数,这远远高于我的Maps API查询限制。我想将它们隔开约100毫秒以防止这种情况发生。我尝试使用setInterval来实现这一点,但似乎geocodeAddress行同时为所有条目运行,因此这只会延迟所有函数,而不是每个函数之间的长度。

我是否有另一种方法可以提取此json数据而不是使用ajax,或者只是一种方法来单独延迟每个API请求?

geocodeAddress函数供参考(它既包含地理编码,也包括绘图标记)

function geocodeAddress(geocoder, resultsMap, person) {

  //geocoding address
  geocoder.geocode({'address': person.Address[0].text}, function(results, status) {
      if (status === 'OK') {

        //plotting coordinate as marker
        var marker = new google.maps.Marker({
            map: resultsMap,
            position: results[0].geometry.location,
            icon: {
              url: person.Image[0].src,
              size: new google.maps.Size(120, 150),
              scaledSize: new google.maps.Size(30, 38),
              origin: new google.maps.Point(0, 0),
              anchor: new google.maps.Point(15, 19)
            }
        });

      } else {
          console.log("Geocode was not successful for the following reason: " + status);
      }
  });
}

3 个答案:

答案 0 :(得分:1)

您可以使用如下所示的100毫秒间隔时间循环geocodeAddress来电,

$.ajax({
    url: 'directory.json',
    dataType: 'json',
    type: 'get',
    cache: 'false',
    success: function(data) {
        var i = 0;
        var loop = function(){
            if(i < data.group.length){
                if (typeof data.group[i].Address != "undefined")
                   geocodeAddress(geocoder, map, data.group[i]);
                i++; 
                setTimeout(loop, 100);
            }
        }
        loop();
    }
});
希望它有所帮助。

答案 1 :(得分:0)

您可以使用IIFE中的setTimeout为数组迭代添加延迟:

$.ajax({
  url: 'directory.json',
  dataType: 'json',
  type: 'get',
  cache: 'false',
  success: function(data) {
    //Invoke delayLoop with initial params - i = 0, delay = 100ms
    (delayLoop)(0, data.group, 100, geocodePerson);
  }
});

//Function to perform delayed iteration function on array elements
function delayLoop (i, list, interval, itemFunc) {
  setTimeout(function() {
    itemFunc(list[i]);
    if (++i < list.length) {
      delayLoop(i, list, interval, itemFunc);
    }
  }, interval)
}

//function to perform on array elements
function geocodePerson(person) {
  if (typeof person.Address != "undefined") {
    geocodeAddress(geocoder, map, person);
  }
}

答案 2 :(得分:0)

使用geocodeAddress函数的一个mod,添加一个可选的回调

function geocodeAddress(geocoder, resultsMap, person, callback) {
    //geocoding address
    geocoder.geocode({
        'address': person.Address[0].text
    }, function(results, status) {
        if (status === 'OK') {

            //plotting coordinate as marker
            var marker = new google.maps.Marker({
                map: resultsMap,
                position: results[0].geometry.location,
                icon: {
                    url: person.Image[0].src,
                    size: new google.maps.Size(120, 150),
                    scaledSize: new google.maps.Size(30, 38),
                    origin: new google.maps.Point(0, 0),
                    anchor: new google.maps.Point(15, 19)
                }
            });

        } else {
            console.log("Geocode was not successful for the following reason: " + status);
        }
        if (typeof callback == 'function') {
            callback();
        }
    });
}

并且,为了进行最小的更改,为geocodeAddress添加一个返回Promise的包装函数

function geocodeAddressPromise(geocoder, resultsMap, person) {
    return new Promise(function(resolve) {
        geocodeAddress(geocoder, resultsMap, person, resolve);
    };
}

您的主要代码可以写成:

$.ajax({
    url: 'directory.json',
    dataType: 'json',
    type: 'get',
    cache: 'false'
}).then(function(data) {
    return data.group.filter(function(person) {
        return typeof person.Address != "undefined";
    }).reduce(function(promise, person) {
        return promise.then(function() {
            return geocodeAddressPromise(geocoder, map, person);
        }).then(function() {
            return new Promise(function(resolve) {
                setTimeout(resolve, 100);
            });
        });
    }, Promise.resolve());
});

它使用.filter只包含地址

的人

和一个相当常见的.reduce模式,依次链接Promises,在一个地址的分辨率和下一个地理编码调用的开始之间增加100ms的超时