我一直在使用Web应用程序遇到Javascript Out of Memory错误,该应用程序加载Google Map并从一个点连续平移到另一个点。它需要大约半天才能耗尽内存,但我真的希望它能持续更长时间。一世 已经确定使用map.panTo方法时会发生内存泄漏 我非常怀疑它可能是我使用它的方式(Javascript不是我强大的 适合)。你能看一下这段代码并帮我修复这个内存泄漏吗?为了节省调试时间,我加快了它在这个演示代码中的间隔(即使通过检查Windows任务管理器中的过程,泄漏也很明显)。这使用ASP .Net 3.5 Web窗体,但没有PostBacks,代码完全是HTML,CSS和Javascript。它泄漏了IE中最糟糕的情况(我需要用它来显示它)。
修改
代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Map Shifter</title>
<style type="text/css">
#divMap { height: 400px; width:400px; position:absolute; top:10%; left:10%; border: 2px solid #ff1100; }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=2&sensor=false"></script>
<script type="text/javascript" language="javascript">
//Have tried both HashTable and Array (Both Leak)...
var m_arrMaps = new HashTable(); //new Array();
var m_Timer;
function HashTable() {
return this;
}
function LoadMapAndStartShifting() {
var objMapCenterPoint = new google.maps.LatLng(20.5, -156);
var objMapOptions = { zoom: 9, center: objMapCenterPoint, mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: false, streetViewControl:false, zoomControl: false, mapTypeControl: false, panControl: false
}
var map = new google.maps.Map(document.getElementById("divMap"), objMapOptions);
m_arrMaps["ShiftingMap"] = map;
setTimeout("ShiftMap(20.5, -156);", 700);
}
function ShiftMap(decLat, decLng) {
var objLatLong = new google.maps.LatLng(decLat, decLng);
//Have tried setCenter instead of preferred panTo and it still leaks!
m_arrMaps["ShiftingMap"].panTo(objLatLong);
if (decLat == 20.5) {
//Leaks...
ResetTimer(39, -87);
}
else {
//Still leaks...
setTimeout("ShiftMap(20.5, -156);", 700);
}
}
function ResetTimer(decLat, decLng) {
m_Timer = setTimeout("ShiftMap(" + decLat + ", " + decLng + ");", 700);
}
</script>
</head>
<body onload="LoadMapAndStartShifting();">
<form id="form1" runat="server">
<div id="divMap"></div>
</form>
</body>
答案 0 :(得分:2)
为什么要为地图创建哈希表?您可以将地图创建为全局变量。我会感到惊讶,但是你的评论“//已经尝试了HashTable和Array(两个泄漏)......”让我想知道为什么你需要哈希表或数组。
你也可以通过将选项结构直接传递给Map()函数来删除objMapOptions和objMapCenterPoint变量,同样将latLng传递给panTo()函数。
<script type="text/javascript" language="javascript">
var m_Timer, map;
function LoadMapAndStartShifting() {
map = new google.maps.Map(document.getElementById("divMap"), { zoom: 9, center: new google.maps.LatLng(20.5, -156), mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: false, streetViewControl:false, zoomControl: false, mapTypeControl: false, panControl: false
});
setTimeout("ShiftMap(20.5, -156);", 700);
}
function ShiftMap(decLat, decLng) {
map.panTo(new google.maps.LatLng(decLat, decLng));
if (decLat == 20.5) {
//Leaks...
ResetTimer(39, -87);
}
else {
//Still leaks...
setTimeout("ShiftMap(20.5, -156);", 700);
}
}
function ResetTimer(decLat, decLng) {
m_Timer = setTimeout("ShiftMap(" + decLat + ", " + decLng + ");", 700);
}
</script>
另一个建议是,如何缓存地图?我不知道这个示例代码是否实际上是你正在做的,但是如果它只是以这种方式在两个地图之间移动,你不能使用静态地图api,并缓存图像并只使用javascript旋转图象?
答案 1 :(得分:2)
看起来你只在“Hashtable”对象中存储了一个元素 - [“ShiftingMap”] - 它不是持有地图,而是持有一张地图。您可以使用全局变量来保存地图对象。
唯一重复的分配是为每个平底锅创建的new google.maps.LatLng(decLat, decLng)
。
建议:
1)LatLng的文档没有给出任何关于需要显式释放对象的警告,所以垃圾收集器可能应该处理它。
2)考虑整体问题 - 您尝试连续平移Google地图6小时或更长时间。为什么你认为泄漏在你的代码中?这个问题更有可能出现在G Maps中。可能下载的地图图像切片保存在本地,因为用户可能想要反击。
作为测试,尝试在两点之间来回平移,而不是在全球范围内进行当前平移。 (如果我理解你的相对转移是正确的。)
查看泄漏是否以内存/小时的速率发生
3)请务必查看不同的浏览器是否会以不同方式影响您的问题。 Esp尝试Google Chrome。
<强>加强>
我重新编写了您的演示代码,将LatLng调用移出循环,但仍然存在泄漏。此外,最好在setTimeout
次调用中使用非字符串值,因此我也改变了这一点。我还使用Maps API tutorial将doctype设置为他们推荐的内容。
结果如下。它泄露在FF和Chrome上。我在官方Google Maps API v3 forum提交了一个帖子。
.panTo
方法漏洞似乎很明显。我想你的下一步是看看Google员工是否回复帖子。
重写测试用例:
<!DOCTYPE html>
<html>
<!-- http://sandbox.kluger.com/map_demo.html -->
<!-- See tutorial http://code.google.com/apis/maps/documentation/javascript/tutorial.html -->
<head>
<title>Map Shifter</title>
<style type="text/css">
#divMap { height: 400px; width:400px; position:absolute; top:10%;
left:10%; border: 2px solid #ff1100; }
</style>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" language="javascript">
// Globals
var map,
mapCenterPoints,
currentPoint;
var ShiftMap = function() {
currentPoint = currentPoint == 0 ? 1 : 0; // update
map.panTo(mapCenterPoints[currentPoint]);
setTimeout(ShiftMap, 700);
}
function LoadMapAndStartShifting() {
mapCenterPoints = [new google.maps.LatLng(20.5, -156),
new google.maps.LatLng(39, -87)];
currentPoint = 0;
var objMapOptions = { zoom: 9,
center: mapCenterPoints[currentPoint],
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: false, streetViewControl:false,
zoomControl: false, mapTypeControl: false,
panControl: false
}
map = new google.maps.Map(document.getElementById("divMap"),
objMapOptions);
setTimeout(ShiftMap, 700);
}
</script>
</head>
<body onload="LoadMapAndStartShifting();">
<div id="divMap"></div>
</body>
</html>
答案 2 :(得分:2)
刚才有另一个想法。您指定v = 2,即获取此API的版本2发行版。目前的版本是3.6。建议您尝试更新版本号(或者只是删除v参数以获取最新的稳定版本)并查看是否可以改进版本。可能他们在最近的版本中整理了任何垃圾收集。
答案 3 :(得分:1)
使用JavaScript循环访问数据后,您可以尝试刷新页面。这可能会释放页面上运行的脚本使用的内存: