Javascript闭包 - 将infowindow id传递给for循环

时间:2013-12-28 14:50:15

标签: javascript ajax google-maps google-maps-api-3 closures

使用循环将infowindows放置在地图上。他们的内容是通过AJAX调用生成的。 AJAX的URL由同一个循环决定。如果在呈现页面后调用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

如您所见,因为一旦循环结束就调用了AJAX函数,i变量就不再相关了。

我不能将AJAX函数放在setContent中,因为它会输出undefined

作为解决方案,我想到的是将infowindow id传递给AJAX函数getStationInfo并以这种方式设置所需的URL,但我无法理解如何做到这一点。也许以某种方式使用this

这里的最终目标是从服务器检索相关文件。然后我可以解析并将其附加到infowindow。

如果有另一种方法可以解决这个问题,我肯定想了解它。非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

你正在尝试使用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
}

正确的方法是在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));

这样你就可以在循环内的任何地方使用markeri,即使它是在ajax中 回调 - 由于闭包,它将在循环运行期间正确设置

答案 1 :(得分:1)

工作代码:

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

改变了什么?

  1. id变量polyNames[i]从循环内发送到AJAX函数getStationInfo
  2. infoWindowDiv功能变得多余。
  3. 将AddListerner更改为AddListenerOnce以避免重复。