【问题标题】:How can I escape $.each loop with my data?如何使用我的数据逃避 $.each 循环?
【发布时间】:2017-07-02 09:39:20
【问题描述】:

我正在进行 Json 调用以检索位置列表,其中包含每个位置的详细信息。此信息中包含经度和纬度。

我正在使用 Google 的距离矩阵 api 来获取与在 url 中作为查询提供的坐标的距离。

我认为最合乎逻辑的方法是遍历位置并比较每个位置的搜索坐标和位置坐标。我将从距离矩阵调用返回的一些信息附加到我的数据数组中。

除了从距离矩阵返回的数据只能在距离矩阵的返回函数中使用之外,这很好用。我将所需数据从距离矩阵返回函数传递到矩阵返回函数之外但仍在 $.each 循环内的函数中。这似乎是解决我的问题的一步,但我被困住了。

我需要使用原始数据,但附加了距离矩阵数据,以便我可以按距离对数据中的项目进行排序并输出。我认为排序函数在 $.each 循环内不能很好地工作,所以我需要在数据的附加版本完好无损的情况下跳出循环。至少我认为。任何帮助,将不胜感激。

var ltlg = [];
var sLat = parseFloat(35.2219971);
var sLng = parseFloat(-101.83129689999998);
var sLatLng = {lat: sLat, lng: sLng};

var locLat;
var locLng;
var locLatLng = [];

$.getJSON("file.json",function(data){

    if(sLat && sLng) {

        $.each(data, function(x, y){

            locLat = data[x].Address.Location.Latitude;
            locLng = data[x].Address.Location.Longitude;

            //locLatLng.push({lat: locLat, lng: locLng});

            var service = new google.maps.DistanceMatrixService;

            service.getDistanceMatrix({
                origins: [sLatLng],
                destinations: [{lat: locLat, lng: locLng}],
                travelMode: 'DRIVING',
                unitSystem: google.maps.UnitSystem.IMPERIAL,
                avoidHighways: false,
                avoidTolls: false
            }, function(response, status) {
                if (status !== 'OK') {          
                    console.log('status is ' + status);        
                } else {
                    var distance = response.rows[0].elements[0].distance.value;
                    var miles = response.rows[0].elements[0].distance.text;
                    var time = response.rows[0].elements[0].duration.text;

                    addData(distance, miles, time);
                }

            });

            function addData(distance, miles, time) {
                data[x]["distance"] = distance;
                data[x]["miles"] = miles;
                data[x]["time"] = time;
            }

        });

        console.log(JSON.stringify(data));

    } else {
        console.log('no query');
    }

});

我用静态 lat lng 替换了 sn-p 的查询变量。

【问题讨论】:

  • 你为什么不使用 Array.map/forEach/filter ?
  • @Jonasw 我不知道该怎么做。可以举个例子吗?
  • 请不要破坏您的帖子。通过在 Stack Exchange 网络上发布,您已授予 SE 分发该内容的不可撤销的权利(在 CC BY-SA 3.0 license 下)。根据 SE 政策,任何破坏行为都将被撤销。如果您想取消此帖子与您的帐户的关联,请参阅What is the proper route for a disassociation request?
  • @JSum 不幸的是,Stack Exchange 保留了所有问题和答案的所有编辑的版本历史记录。据我所知,一旦敏感信息发布在网站上,就无法 100% 修改敏感信息,除非可以联系网站所有者并要求手动删除历史记录,但我不确定。

标签: javascript arrays sorting for-loop


【解决方案1】:

你可能想要实现一个全局回调,比如:

function loaddata(callback){
  var counter=0;
  data.forEach(function(y,x){
    //get data
   function addData(distance, miles, time) {
     data[x]["distance"] = distance;
     data[x]["miles"] = miles; 
     data[x]["time"] = time;
     if(++counter==data.length){
      callback(data);
     }
   }
  });
}

所以你可以这样做:

loaddata(function(data){
 console.log(data);
});

数据现在包含距离、英里和时间。

【讨论】:

【解决方案2】:

@Jonasw 提供的答案过于复杂,因为每次迭代都会声明一个新的addData(),并且初始化一个完全没有意义的counter,这会消耗大量内存,可以通过更聪明的方法。由于您对每个数据点都有异步回调,并且您希望所有这些都完成,因此最有意义的方法是使用Promise.all()

var sLat = 35.2219971;
var sLng = -101.83129689999998;
var sLatLng = {
  lat: sLat,
  lng: sLng
};

var service = new google.maps.DistanceMatrixService;

function serviceCallback(value, resolve, response, status) {
  if (status !== 'OK') {
    console.log('status is ' + status);

    reject(status);
  } else {
    value.distance = response.rows[0].elements[0].distance.value;
    value.miles = response.rows[0].elements[0].distance.text;
    value.time = response.rows[0].elements[0].duration.text;

    resolve(value);
  }
}

function promiseExecutor(value, resolve, reject) {
  service.getDistanceMatrix({
    origins: [sLatLng],
    destinations: [{
      lat: value.Address.Location.Latitude,
      lng: value.Address.Location.Longitude
    }],
    travelMode: 'DRIVING',
    unitSystem: google.maps.UnitSystem.IMPERIAL,
    avoidHighways: false,
    avoidTolls: false
  }, serviceCallback.bind(null, value, resolve));
}

$.getJSON("file.json", function (data) {
  if (![sLat, sLng].some(isNaN)) {
    Promise.all(data.map(function (value) {
      return new Promise(promiseExecutor.bind(null, value));
    })).then(function (data) {
      console.log(JSON.stringify(data, null, 2));
    });
  } else {
    console.log('no query');
  }
});

但是,当您能够一次为每个数据点创建一个请求时,我看到您正在为每个单独的数据点发出请求,因此为了节省更多资源,您可以尝试以下操作:

var sLat = 35.2219971;
var sLng = -101.83129689999998;
var sLatLng = {
  lat: sLat,
  lng: sLng
};

var service = new google.maps.DistanceMatrixService;

$.getJSON("file.json", function (data) {
  if (![sLat, sLng].some(isNaN)) {
    service.getDistanceMatrix({
      origins: [sLatLng],
      destinations: data.map(function (value) {
        return {
          lat: value.Address.Location.Latitude,
          lng: value.Address.Location.Longitude
        };
      }),
      travelMode: 'DRIVING',
      unitSystem: google.maps.UnitSystem.IMPERIAL,
      avoidHighways: false,
      avoidTolls: false
    }, function (response, status) {
      if (status !== 'OK') {
        console.log('status is ' + status);
      } else {
        response.rows[0].elements.forEach(function (element, index) {
          if (element.status === 'OK') {
            data[index].distance = element.distance.value;
            data[index].miles = element.distance.text;
            data[index].time = element.duration.text;
          }
        });

        console.log(JSON.stringify(data, null, 2));
      }
    });
  } else {
    console.log('no query');
  }
});

【讨论】:

  • @Jonasw 零承诺怎么样? :P
猜你喜欢
  • 1970-01-01
  • 2021-05-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-04
  • 2011-05-12
相关资源
最近更新 更多