我有一个JavaScript ajax页面,它每20秒触发一次ajax请求(使用setInterval函数),并以JSON
格式获得响应。在页面中;使用JSON
响应我在Google地图上显示标记(使用API v3),并根据从ajax
响应收到的位置每20秒更新一次。我在标记的点击事件上显示infoWindow
。
我使用PHP作为服务器端脚本,通过执行一些数据库调用来生成我的ajax响应。
打开页面时,一切正常。但慢慢地页面开始响应缓慢。我的意思是当我点击标记或相关文本时,页面需要很长时间才能找到标记,加载地图并打开infoWindow
。随着时间的推移,页面的缓慢增加。如果我刷新页面,一切都会开始正常工作。
该页面在任何时间点都不显示单个错误,我必须补充说,标记位置的自动更新在页面的整个生命周期内都能正常工作。
我尝试过在论坛上找到的所有内容。就像,我已经从json
回复转到了xml(dom)
回复。我已经尝试更改XMLHttpRequest
方法,因为GET请求倾向于自动缓存数据。但没有任何帮助我。我完全无能为力,出了什么问题,我在代码中做了什么。
这是我的JavaScript代码:
<script type="text/javascript">
var map;
var contentString = "";
var infoWindow = new google.maps.InfoWindow({content: contentString});
var url = "genAjaxResponse.php?id=<?php echo $id; ?>";
var marker;
var gmarkers = new Array();
var icon;
var lastClickedMarker;
var stImgId;
var customIcons = {
Moving: {
icon: 'icons/abc.png'
},
Idle: {
icon: 'icons/xyz.png'
},
Parked: {
icon: 'icons/pqr.png'
},
Alert: {
icon: 'icons/wxy.png'
}
};
function load() { // to be called on onload event of body
map = new google.maps.Map(document.getElementById("map"), {
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true,
center:new google.maps.LatLng(15.570128,78.957092)
});
calldownloadUrl(url,map,infoWindow);
directionsDisplay = new google.maps.DirectionsRenderer();
}
function calldownloadUrl(url,map,infoWindow) {
downloadUrl(url,displayMarker,map,infoWindow);
}
function displayMarker(data,map,infoWindow) {
function generateTriggerCallback(object, eventType) {
return function() {
google.maps.event.trigger(object, eventType);
};
}
var namearr = Array();
var json = data.responseText;
var vehicles = eval ("(" + json + ")");
var i = 0;
for (var veh in vehicles)
{
var tag = vehicles[veh];
var veh_no = tag["veh_no"];
var is_stale = tag["is_stale"];
var ignition_off = tag["ignition_off"];
var speed = tag["speed"];
var lat = tag["lat"];
var lng = tag["lng"];
var time = tag["time_stamp"];
var address = tag["address"];
var point = new google.maps.LatLng(
parseFloat(lat),
parseFloat(lng));
var type;
var status;
stImgId = i+1;
if(ignition_off == 0 && speed > 3) {
type = "Moving";
status = type + "(" + speed + " Kmph)";
document.getElementById("img"+stImgId).src = "icons/greenalert2.png";
}
else {
if(ignition_off == 1) {
type = "Parked";
status = type;
document.getElementById("img"+stImgId).src = "icons/greyalert2.png";
}
else {
type = "Idle";
status = type;
document.getElementById("img"+stImgId).src = "icons/yellowalert2.png";
}
}
if(is_stale == 1) {
type = "Alert";
status = type;
document.getElementById("img"+stImgId).src = "icons/redalert2.png";
}
infoWindow.close();
var icon = customIcons[type] || {};
if(typeof gmarkers[i] != 'undefined') {
gmarkers[i].setPosition(point);
gmarkers[i].setIcon(icon.icon);
if(gmarkers[i].id == lastClickedMarker) {
if(map.getBounds().contains(gmarkers[i].getPosition()) === false)
map.setCenter(gmarkers[i].getPosition());
}
}
else
{
gmarkers[i] = new google.maps.Marker({
id: i,
position: point,
icon: icon.icon,
title: veh_no,
map: map
});
}
var html = "<span><p><b>"+veh_no +"</b></p> <p>Address: "+address+"<br />Status: "+status+"<br />Time: "+time+"</p></span>";
namearr[i] = "<span><p><b>"+veh_no +"</b></p> <p>Address: "+address+"<br />Status: "+status+"<br />Time: "+time+"</p></span>";
// -- bind click event to texts (vehicle nos) -- //
var textclick = document.getElementById(i);
textclick.onclick = generateTriggerCallback(gmarkers[i],"click");
// -- bind click event to markers -- //
bindinfoWindow(gmarkers[i], map, infoWindow, namearr[i], icon);
i++;
}
}
function bindinfoWindow(marker, map, infoWindow, html, icon) {
google.maps.event.addListener(marker, 'click', function() {
lastClickedMarker = marker.id;
map.setCenter(marker.getPosition());
if(map.zoom < 15)
map.setZoom(15);
marker.setIcon(icon.icon);
marker.setZIndex(google.maps.Marker.MAX_ZINDEX + 1);
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback, map, infoWindow) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, map, infoWindow, request.status);
}
};
request.open('GET', url, true);
request.send();
}
function doNothing() {}
window.setInterval(function() {calldownloadUrl(url,map,infoWindow)},20000);
</script>
答案 0 :(得分:0)
我认为每次调用ajax请求时都需要清空gmarkers
数组,或者在处理接收到的数据之前重置i
变量。这样您就不会将所有新标记添加到以前的标记中,这似乎是代码中的瓶颈。
P.S。我没有测试你的代码。我只是在猜测。
答案 1 :(得分:0)
我有一个类似的应用程序,我也遇到了类似的行为。 就我而言,我每30秒更新一次标记数组(对于每个标记:位置,图标,听众的内容)。
首先,我已经停止为每次更新创建一个新标记,我认为设置markers[id].setMap(null);
并创建一个新标记就可以了,CG会处理这个。
然后我已将代码更改为仅更新标记位置,图标和侦听器,如下所示:
this.markers[id].setPosition(new google.maps.LatLng(lat, lng));
this.markers[id].setIcon(this.updateFlags(status, id));
google.maps.event.addListener(this.markers[id], 'mouseover', function () {
infoWindow.setContent(text);
infoWindow.open(this.map, this);
});
google.maps.event.addListener(this.markers[id], 'click', function () {
devices.selectDevice(index);
});
这会产生更少的内存消耗,但仍然......
终于我编辑了这样的代码:
this.markers[id].setPosition(new google.maps.LatLng(lat, lng));
this.markers[id].setIcon(this.updateFlags(status, id));
google.maps.event.clearListeners(this.markers[id], 'mouseover');
google.maps.event.clearListeners(this.markers[id], 'click');
google.maps.event.addListener(this.markers[id], 'mouseover', function () {
infoWindow.setContent(text);
infoWindow.open(this.map, this);
});
google.maps.event.addListener(this.markers[id], 'click', function () {
devices.selectDevice(index);
});
我在 Chrome开发者工具(F12) - &gt;中进行了测试Profiler 和快照堆快照。你会看到它是否增长太快。
所以在你的情况下,这意味着将这一行添加为函数bindinfoWindow()的第一行:
google.maps.event.clearListeners(marker, 'click');