当前位置: 代码迷 >> Web前端 >> 从webQQ谈iframe内存释放有关问题
  详细解决方案

从webQQ谈iframe内存释放有关问题

热度:214   发布时间:2012-10-24 14:15:58.0
从webQQ谈iframe内存释放问题

随着Ajax的发展,使用javascriptRIA应用越来越多,用户在同一页面中驻留的时间越来越长,内存泄露和内存占用问题越来越值得RIA开发者的注意,当RIA应用中内存得不到合理的释放,内存使用量会持续上涨,造成RIA应用反应变慢甚至会造成用户浏览器崩溃。虽然这种问题很少显现,但并不是说明应用中不存在这种问题,只不过这些问题在用户页面跳转和关闭浏览器时被掩盖掉,当我们RIA应用要用户一直在同一页面中操作时,这些问题就会显现出来,webQQ(http://web2.qq.com/)正是这样一个典型的应用。在这些问题中比较显著的一个就是iframe的内存泄露问题,由于iframe的引用页会占用相对大量的内存,如果iframe得不到释放,内存会明显的增长。

?

webQQ中,QQ空间、QQ邮箱、腾讯微博等都是通过iframe的方式引入的,而这些引用都是可关闭的,如何做到关闭时释放iframe和引用页所占用的内存?下面通过一个例子来看看,会出现什么问题和如何解决这些问题。

?

问题1:

<!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>
  <TITLE>kjah.iteye.com</TITLE>
	<SCRIPT LANGUAGE="JavaScript">
	<!--
		$=function(s){return document.getElementById(s)}
		window.onload=function(){
			var t=[];
			var btn1=$('btn1'),btn2=$('btn2'),btn3=$('btn3');
			btn1.onclick=function(){
				if($('ifm1'))return;
				var c=$('content');
				var ifm=document.createElement('iframe');
				ifm.src='http://www.sohu.com';
				ifm.id='ifm1';
				c.appendChild(ifm);
				t.push(ifm);
			}
			btn2.onclick=function(){
				var ifm=$('ifm1');
				ifm.parentNode.removeChild(ifm);
			}
		}
	//-->
	</SCRIPT>
 </HEAD>
 <BODY>
	  <input id="btn1" type="button" value="打开"/> 
	  <input id="btn2" type="button" value="关闭"/>
	  <div id="content"></div>
	  <span style="color:#eee">http://kjah.iteye.com</span>
 </BODY>
</HTML>

?

?

数组t用来保持那些iframe的引用,模拟发生闭包引用dom对象,造成无法释放的情况。

windows系统的任务管理器来观察内存使用情况,在打开iframe时内存会增长,而关闭时没有释放,由于之前的实例还被引用,再次打开时,内存会继续增长。以上是在IE下测试的结果,FF有很大好转。

?

?

问题2

<!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>
  <TITLE>kjah.iteye.com</TITLE>
	<SCRIPT LANGUAGE="JavaScript">
	<!--
		$=function(s){return document.getElementById(s)}
		window.onload=function(){
			//var t=[];
			var btn1=$('btn1'),btn2=$('btn2'),btn3=$('btn3');
			btn1.onclick=function(){
				if($('ifm1'))return;
				var c=$('content');
				var ifm=document.createElement('iframe');
				ifm.src='http://www.sohu.com';
				ifm.id='ifm1';
				c.appendChild(ifm);
				//t.push(ifm);
			}
			btn2.onclick=function(){
				var ifm=$('ifm1');
				ifm.parentNode.removeChild(ifm);
			}
		}
	//-->
	</SCRIPT>
 </HEAD>
 <BODY>
	  <input id="btn1" type="button" value="打开"/> 
	  <input id="btn2" type="button" value="关闭"/>
	  <div id="content"></div>
	  <span style="color:#eee">http://kjah.iteye.com</span>
 </BODY>
</HTML>

?

在较复杂的javascript RIA应用中,由于开发人员技术水平等原因,造成这种不能释放DOM对象的情况很容易发生,查找这些引用非常困难。好在一般的DOM对象占用内存较少,即使不能释放(这里不包括内存泄露的对象)内存增长也不会很明显。在这个例子中,把数组t和相关的处理去掉,再来看内存的增长情况,发现多次打开iframe不会出现内存的持续增长,但在关闭时也没有得到大量释放,只是在再次打开iframe时,内存没有继续增长,感觉是把iframe给缓存住了。

?

?

?

?解决办法

如何解决iframe的内存占用与内存增长的情况?不管是iframe引用无法释放的问题,还是iframe缓存的问题,通过把iframe对象的src置空,释放iframec所引用的页面内容是一个行之有效的办法,虽然iframe还是没有释放,但是它所占用的内存已大部分被释放掉。

<!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>
  <TITLE>kjah.iteye.com</TITLE>
	<SCRIPT LANGUAGE="JavaScript">
	<!--
		$=function(s){return document.getElementById(s)}
		window.onload=function(){
			var t=[];
			var btn1=$('btn1'),btn2=$('btn2'),btn3=$('btn3');
			btn1.onclick=function(){
				if($('ifm1'))return;
				var c=$('content');
				var ifm=document.createElement('iframe');
				ifm.src='http://www.sohu.com';
				ifm.id='ifm1';
				c.appendChild(ifm);
				t.push(ifm);
			}
			btn2.onclick=function(){
				var ifm=$('ifm1');
				ifm.src="";
				ifm.parentNode.removeChild(ifm);
			}
		}
	//-->
	</SCRIPT>
 </HEAD>
 <BODY>
	  <input id="btn1" type="button" value="打开"/> 
	  <input id="btn2" type="button" value="关闭"/>
	  <div id="content"></div>
	  <span style="color:#eee">http://kjah.iteye.com</span>
 </BODY>
</HTML>

?

?

?

通过观察,在移除iframe时,内存占用有一个明显减少。

1 楼 mercyblitz 2010-12-10  
不释放IFrame是什么浏览器?难道都有?
2 楼 dengzhangtao 2010-12-11  
iframe 所引用的src 学习了。
3 楼 limu 2010-12-12  
学习啦,这方面以前还真没看到相关的分析和介绍.
4 楼 jokiye 2010-12-14  
webQQ中又是如何解决的呢
5 楼 yuhe 2010-12-14  


楼主大牛。
6 楼 左看右看 2010-12-15  
很好,涨见识了!
7 楼 xgrass18 2010-12-17  
鼠标一抖 顶变成踩了。。。
8 楼 yunchow 2010-12-17  
思路清晰,写的不错
9 楼 lionfox 2010-12-17  
恩,同样,iframe还存在另外一个问题:
就是加载src完成之后,在状态栏还在慢慢的滚动,给人的感觉是页面没有加载完毕,因为我们项目中遇到这个问题,不过通过搜索也解决了。
10 楼 lionfox 2010-12-17  
lionfox 写道
恩,同样,iframe还存在另外一个问题:
就是加载src完成之后,在状态栏还在慢慢的滚动,给人的感觉是页面没有加载完毕,因为我们项目中遇到这个问题,不过通过搜索也解决了。

这个不是每次都出现,通常第一次的时候会这样,即便是最简单的页面
11 楼 onlylau 2010-12-22  
学习了,不过我测试的时候,第一种情况下确实发现内存没有释放;但是第三个解决方法怎么我测试的时候效果跟第二个差不多,不怎么明显啊?
12 楼 xiaodond 2011-01-07  
将src弄成空不错。。
  相关解决方案