简体   繁体   English

Javascript闭包-在for循环中传递infowindow id

[英]Javascript closures - passing infowindow id inside for loop

The infowindows are placed on the map using a loop. 信息窗口使用循环放置在地图上。 Their content is generated with an AJAX call. 它们的内容是通过AJAX调用生成的。 The AJAX's URL is determined by that same loop. AJAX的URL由同一循环确定。 If I call the AJAX function once the page has been rendered, then the loop is over and I can no longer use the counter i . 如果在页面渲染完毕后调用AJAX函数,则循环结束,并且我将无法再使用计数器i

var xhr = "";
var markers = [];
var infowindow = new google.maps.InfoWindow();

//Sample array
var polylineCoordinates = [new google.maps.LatLng(78.782762, 17.917843),
                           new google.maps.LatLng(-0.829439, -91.112473),
                           new google.maps.LatLng(15.066156, -23.621399),
                          ]

var polylineNames = [one,
                     two,
                     three,
                          ]


function createHttpRequest() {
    try {   
        xhr = new XMLHttpRequest();
        return xhr;
        }
        catch (e)
        {
            //assume IE6
            try {
            xhr = new activeXBbject("microsoft.XMLHTTP");
            return xhr;
            }
            catch (e)   {
                return alert("Unable to create an XMLHttpRequest object");
            }
        }
}



  function initialize() {

    var mapOptions = {
      center: new google.maps.LatLng(78.782762,17.917843),
      zoom: 10,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
        map = new google.maps.Map(document.getElementById("map_canvas"),
        mapOptions);
  }




    var marker, i;

    for (i = 0; i < polylineCoordinates.length; i++) {  
      marker = new google.maps.Marker({
        position: polylineCoordinates[i],
        map: map
      });
      markers.push(marker);

            google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          infowindow.setContent("<div id=\""polylineNames[i]"\" style=\"height:50px;width:200px;\">"+polylineNames[i]+"</div>");

      infowindow.open(map, marker);

      google.maps.event.addListener(infowindow,"domready", function(){
      getStationInfo(infoWindowDiv);
            });
    }
  })(marker, i));

}//End polylineCoordinates loop (adding markers loop)


    function infoWindowDiv(doc){
       //doc can be parsed here and displayed in the infowindow
          }

   function getStationInfo(callback) {
    var xhr = createHttpRequest();
    //***This will no longer work as the loop is over. How do I get the infowindow div id?
    var url = "Station_"+polylineNames[i]+".php";
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var doc = xhr.responseXML;
                return callback(doc)
        }//end readyState

    }//end readystatechange
    xhr.open("GET",url,true);
    xhr.send(null);
}//end getStationInfo

As you can see, because the AJAX function is called once the loop is over, the i variable is no longer relevant. 如您所见,由于循环结束后会调用AJAX函数,因此i变量不再相关。

I can't just put the AJAX function inside the setContent because that outputs undefined . 我不能只是将AJAX函数放在setContent内,因为这会输出undefined

What I had in mind as a solution was passing the infowindow id to the AJAX function getStationInfo and setting the wanted url that way, but I couldn't wrap my head around how to do that. 作为解决方案,我想到的是将infowindow id传递给AJAX函数getStationInfo并以这种方式设置所需的url,但是我无法解决该问题。 Perhaps using this somehow? 也许以某种方式使用this

The ultimate goal here is to retrieve the relevant file from the server. 这里的最终目标是从服务器检索相关文件。 Then I can parse and append it to the infowindow. 然后,我可以解析并将其附加到信息窗口。

And if there's another method of how to go about this, I'd sure like to know about it. 如果还有另一种解决方法,我一定想知道。 Any help greatly appreciated. 任何帮助,不胜感激。

You are trying to use javascript closures but you do it the wrong way - in the setting of the google event handler: 您正在尝试使用javascript闭包,但操作方式错误-在google事件处理程序的设置中:

for (i = 0; i < polylineCoordinates.length; i++) {
    google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
            ....
        }
    })(marker, i));
    # ... do something here
}
function getStationInfo(callback) { 
    # trying to use i here
}

The correct way is to use the closure right inside the for loop, so that it wraps the whole loop, and place the AJAX handler inside the loop: 正确的方法是在for循环内使用闭包,以便将整个循环包装起来,并将AJAX处理程序放入循环内:

for (i = 0; i < polylineCoordinates.length; i++)
(function(marker, i) {
    google.maps.event.addListener(marker, 'click', function() {
            ....
    });

    function getStationInfo(callback) { 
        # you can use i here even if it's an ajax callback
    }
    # you can use marker and i anywhere inside here even if it's in an ajax 
    # callback - it will be set correctly as it was during the loop run
})(marker, i));

This way you can use marker and i anywhere inside the loop even if it's in an ajax callback - thanks to closures it will be set correctly as it was during the loop run . 这样,即使在ajax回调中,您也可以在循环中的任何位置使用markeri 由于使用了闭包,可以像在循环运行期间一样正确地设置它

Working Code: 工作代码:

var xhr = "";
var markers = [];
var infowindow = new google.maps.InfoWindow();

//Sample array
var polylineCoordinates = [new google.maps.LatLng(78.782762, 17.917843),
                           new google.maps.LatLng(-0.829439, -91.112473),
                           new google.maps.LatLng(15.066156, -23.621399),
                          ]

var polylineNames = [one,
                     two,
                     three,
                          ]


function createHttpRequest() {
    try {   
        xhr = new XMLHttpRequest();
        return xhr;
        }
        catch (e)
        {
            //assume IE6
            try {
            xhr = new activeXBbject("microsoft.XMLHTTP");
            return xhr;
            }
            catch (e)   {
                return alert("Unable to create an XMLHttpRequest object");
            }
        }
}



  function initialize() {

    var mapOptions = {
      center: new google.maps.LatLng(78.782762,17.917843),
      zoom: 10,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
        map = new google.maps.Map(document.getElementById("map_canvas"),
        mapOptions);
  }




    var marker, i;

    for (i = 0; i < polylineCoordinates.length; i++) {  
      marker = new google.maps.Marker({
        position: polylineCoordinates[i],
        map: map
      });
      markers.push(marker);

            google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          infowindow.setContent("<div id=\""polylineNames[i]"\" style=\"height:50px;width:200px;\">"+polylineNames[i]+"</div>");

      infowindow.open(map, marker);

      google.maps.event.addListenerOnce(infowindow,"domready", function(){
      getStationInfo(polyNames[i]);
            });
    }
  })(marker, i));

}//End polylineCoordinates loop (adding markers loop)



   function getStationInfo(id) {
    var xhr = createHttpRequest();
    var url = "Station_"+id+".php";
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var doc = xhr.responseXML;
         /*
         ***Begin parsing here or return doc to another function
         */ 
        }//end readyState

    }//end readystatechange
    xhr.open("GET",url,true);
    xhr.send(null);
}//end getStationInfo

What changed? 发生了什么变化?

  1. id variable polyNames[i] is sent to the AJAX function getStationInfo from within the loop. id变量polyNames[i]从循环内发送到AJAX函数getStationInfo
  2. infoWindowDiv function made redundant. infoWindowDiv函数变得多余。
  3. AddListerner changed to AddListenerOnce to avoid duplication. AddListerner更改为AddListenerOnce以避免重复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM