【问题标题】:Iterating through array javascript google maps markers遍历数组 javascript 谷歌地图标记
【发布时间】:2017-07-02 19:55:50
【问题描述】:

问题背景

我有一个包含纬度和经度值的数组。我有下面的代码,它为每次迭代放置一个标记。我正在使用 Ruby gem Gon 将值从数据库传递到 javascript。以下内容按预期工作:

function populateMap(map){
    var index;
    for (index = 0; index < gon.length; ++index) {
      var latlng = new google.maps.LatLng(gon.murals[index].lat, gon.murals[index].long);
      var marker = new google.maps.Marker({
        position: latlng,
        map: map  
      }); 
    }
  }         

但是,我希望为每个带有地址的标记提供一个信息窗口。这是通过反向地理编码完成的。 https://developers.google.com/maps/documentation/javascript/examples/geocoding-reverse

以下代码适用于反向地理编码 1 个标记:

function getReverseGeocodingData(geocoder, map, infowindow) {
      var latlng = new google.maps.LatLng(gon.murals[0].lat, gon.murals[0].long);
      geocoder.geocode({'location': latlng}, function(results, status) {
        if (status === 'OK') {
          if (results[1]) {
            var marker = new google.maps.Marker({
              position: latlng,
              map: map
            });

            google.maps.event.addListener(marker, 'mouseover', function () {
              infowindow.open(map, marker);
              document.getElementById("address").innerHTML = results[1].formatted_address ;
            });           
          } else {
              window.alert('No results found'); 
            }
        } else {
            window.alert('Geocoder failed due to: ' + status);
          }
      }); 
  }  

实际问题 当我将 for 循环添加到反向 geo0code 函数时,它只会放置最后一次迭代的标记。

   function populateMapTest(map, geocoder, infowindow){
    var index;
    for (index = 0; index < gon.murals.length; ++index) {
      var latlng = new google.maps.LatLng(gon.murals[index].lat, gon.murals[index].long);
      alert("start of iteration: " + index);
      geocoder.geocode({'location': latlng}, function(results, status){
        alert("middle of iteration: " + index);
        if (status === 'OK') {
          if (results[1]) {
            var marker = new google.maps.Marker({
              position: latlng,
              map: map
            });

            google.maps.event.addListener(marker, 'mouseover', function () {
              infowindow.open(map, marker);
              document.getElementById("address").innerHTML = results[1].formatted_address ;

            });

          } else {
              window.alert('No results found'); 
            }
        } else {
            window.alert('Geocoder failed due to: ' + status);
          }

      });

      alert("end of iteration: " + index);
    }  
  } 

对于每次迭代,警报按以下顺序排列:迭代开始、迭代结束、迭代中间。它似乎正在跳过地理编码器括号中包含的代码,直到完成所有迭代。我想?

任何帮助表示赞赏。

【问题讨论】:

  • geocoder.geocode 似乎是异步的,因此中间迭代似乎总是在最后运行(例如,在“迭代结束”之后)。

标签: javascript ruby-on-rails ruby google-maps


【解决方案1】:

这听起来像是一个类闭包问题,它与在高范围内声明的变量的范围有关,但在较低范围内的函数中使用并且比实际声明变量的较高范围内持续时间更长。

变化:

var index;
for (index = 0; index < gon.murals.length; ++index) {

到:

for (let index = 0; index < gon.murals.length; ++index) {

这将提供index 块级范围,并且循环的每次迭代都将有自己的index 值。不是循环的所有迭代共享相同的index 值,而是每个迭代都有自己的值。

【讨论】:

  • 感谢您的评论,但它的行为与我的行为完全相同。它会通过每次迭代,然后在最后完成“中间”部分。
【解决方案2】:

这似乎是一个关闭问题。但我认为这可能是因为变量latlng 而不是索引,(或两者兼而有之)。

var latlng = new google.maps.LatLng(gon.murals[index].lat, gon.murals[index].long);

上面的latlng 在整个循环中更新,但最终该函数只使用最后一次迭代的latlng。闭包内的变量(“中间”函数)被引用,并且在函数实际执行时将all更新为最后一个值。 (我想换个思路,就是它真的只看执行时的值,而不是声明)

 var marker = new google.maps.Marker({
          position: latlng,
          map: map
        });

最后,标记将被创建在同一位置,index 次。


例如,下面的代码将打印十个 9,即使您希望它打印一个递增的 x

function foo() {
  for (let index = 0; index < 10; ++index) {
    var x = index;
    setTimeout(function bar() {
      console.log(x)
    }, 10)
  }
}
foo()

但是,如果立即调用它,它将正确打印(当然,这不是您的情况的选择)

function foo() {
  for (let index = 0; index < 10; ++index) {
    var x = index;
    setTimeout(function bar() {
      console.log(x)
    }(), 10)
  }
}
foo()

您可以在中间函数内移动 latlng 声明。 (不过也要检查索引的值,因为这会遇到同样的问题)

【讨论】:

    【解决方案3】:

    这个怎么样:

    geocoder.geocode({'location': latlng}, (function(indexCopy){
      return function(results, status) {
        alert("middle of iteration: " + indexCopy);
        if (status === 'OK') {
          if (results[1]) {
            var marker = new google.maps.Marker({
              position: latlng,
              map: map
            });
    
            google.maps.event.addListener(marker, 'mouseover', function () {
              infowindow.open(map, marker);
              document.getElementById("address").innerHTML = results[1].formatted_address ;
            });
    
          } else {
            window.alert('No results found'); 
          }
        } else {
          window.alert('Geocoder failed due to: ' + status);
        }
    
      };
    })(index));
    

    只是一个想法......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-14
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2014-09-26
      相关资源
      最近更新 更多