JavaScript setTimeout 内存问题
我正在调试一段我认为存在内存泄漏的代码。在 Google Chrome 中运行代码时,浏览器在一段时间后崩溃。我坚信以下代码(为了简单起见,仅附加模板,而不附加整个代码)导致了该问题。当我使用 Chrome 开发者工具的“时间轴”选项卡并观察实际应用程序中的内存使用情况和内存峰值时。如果您注意到播放正在调用transistionTo的代码,并且transistionTo有一个setTimeout函数再次调用播放。我认为内存没有因此被释放。有人可以帮我解决这个问题吗?
var htmlRotatorTimer = '';
function play(src){
// some code here
transitionTo("gallery", "counter");
// some code here
}
function transitionTo(gallery,index) {
// some code here
clearTimeout(htmlRotatorTimer);
htmlRotatorTimer = setTimeout( function(){ play(); }, 1000 );
// some code here
}
play();
这是代码的较长版本
// utility for loading slides
function transitionTo(gallery,index) {
// preloader (optional)
var counterMin = 0;
if (config.preloader) {
counterMin = 1;
if (gallery.length < 3) pause('');
}
var oldCounter = counter;
if((counter >= gallery.length) || (index >= gallery.length)) { counter = counterMin; var e2b = true; }
else if((counter < counterMin) || (index < 0)) { counter = gallery.length-1; var b2e = true; }
else { counter = index; }
// added attr speed in div's
//htmlRotatorTimer = '';
var itemSpeed = Number($(gallery[counter]).attr("speed") != undefined ? $(gallery[counter]).attr("speed") : config.speed);
//htmlRotatorTimer = setInterval(function(){ play(); },itemSpeed);
clearTimeout(htmlRotatorTimer);
htmlRotatorTimer = setTimeout( function(){ play(); }, itemSpeed );
var rmkName = $(gallery[counter].children).attr("id") != undefined ? 'RMK_' + $(gallery[counter].children).attr("id") : '';
var isHtml5 = false;
if (rmkName != '' && eval ('typeof '+ rmkName) == 'object') {
rmkObj = eval(rmkName);
isHtml5 = rmkObj.rmkType == 'html5' ? true : false;
//console.log('html5 is' + rmkObj.rmkType,'obj name' + rmkName, 'typeof:' +(typeof rmkObj));
}
if (config.effect=='fade') {
$(gallery[counter])
.clone()
.appendTo($cont)
.hide()
.fadeIn(config.changeSpeed,function(){$('#showbanners.rmkbanner').css({ 'visibility': 'visible'});if($.browser.msie)this.style.removeAttribute('filter');});
if($cont.children().length>1){
$cont.children().eq(0).css('position','absolute').fadeOut(config.changeSpeed,function(){$(this).remove();});
};
} else if (config.effect=='none') {
$(gallery[counter])
.appendTo($cont);
if($cont.children().length>1){
$cont.children().eq(0).remove();
};
};
// update active class on slide link
if(config.links){
$('.'+uniqueClass+'-active').removeClass(uniqueClass+'-active jshowoff-active');
$('.'+uniqueClass+'-slidelinks a').eq(counter).addClass(uniqueClass+'-active jshowoff-active');
};
// reset for html5 objects only
if (isHtml5) {
rmkObj.preload = 'nopreload';
rmkObj.Reset();
}
};// end function transistionTo
// is the rotator currently in 'play' mode
function isPlaying(){
return $('.'+uniqueClass+'-play').hasClass('jshowoff-paused') ? false : true;
};
// start slide rotation on specified interval
function play(src) {
if (!finalStop) {
if (!isBusy()) {
counter++;
transitionTo(gallery, counter);
if (src == 'hover' || !isPlaying()) {
//htmlRotatorTimer = setInterval(function(){ play(); },config.speed);
clearTimeout(htmlRotatorTimer);
htmlRotatorTimer = setTimeout(function(){
play();
}, config.speed);
}
if (!isPlaying()) {
$('.' + uniqueClass + '-play').text(config.controlText.pause).removeClass('jshowoff-paused ' + uniqueClass + '-paused');
}
};
};
};
I am debugging a code which I think has some memory leak. When running the code in Google Chrome, the browser crashes after a while. I strongly believe the following code (attaching just a template, not the entire code for simplicity) is causing the issue. When I used the Chrome developer tools Timeline tab and watched the memory usage and the memory spikes a lot in the real application. If you notice the code the play is calling transitionTo and transistionTo has a setTimeout function calling play again. I think the memory is not freed because of this. Could anyone please help me in fixing this issue?.
var htmlRotatorTimer = '';
function play(src){
// some code here
transitionTo("gallery", "counter");
// some code here
}
function transitionTo(gallery,index) {
// some code here
clearTimeout(htmlRotatorTimer);
htmlRotatorTimer = setTimeout( function(){ play(); }, 1000 );
// some code here
}
play();
Here's the longer version of the code
// utility for loading slides
function transitionTo(gallery,index) {
// preloader (optional)
var counterMin = 0;
if (config.preloader) {
counterMin = 1;
if (gallery.length < 3) pause('');
}
var oldCounter = counter;
if((counter >= gallery.length) || (index >= gallery.length)) { counter = counterMin; var e2b = true; }
else if((counter < counterMin) || (index < 0)) { counter = gallery.length-1; var b2e = true; }
else { counter = index; }
// added attr speed in div's
//htmlRotatorTimer = '';
var itemSpeed = Number($(gallery[counter]).attr("speed") != undefined ? $(gallery[counter]).attr("speed") : config.speed);
//htmlRotatorTimer = setInterval(function(){ play(); },itemSpeed);
clearTimeout(htmlRotatorTimer);
htmlRotatorTimer = setTimeout( function(){ play(); }, itemSpeed );
var rmkName = $(gallery[counter].children).attr("id") != undefined ? 'RMK_' + $(gallery[counter].children).attr("id") : '';
var isHtml5 = false;
if (rmkName != '' && eval ('typeof '+ rmkName) == 'object') {
rmkObj = eval(rmkName);
isHtml5 = rmkObj.rmkType == 'html5' ? true : false;
//console.log('html5 is' + rmkObj.rmkType,'obj name' + rmkName, 'typeof:' +(typeof rmkObj));
}
if (config.effect=='fade') {
$(gallery[counter])
.clone()
.appendTo($cont)
.hide()
.fadeIn(config.changeSpeed,function(){$('#showbanners.rmkbanner').css({ 'visibility': 'visible'});if($.browser.msie)this.style.removeAttribute('filter');});
if($cont.children().length>1){
$cont.children().eq(0).css('position','absolute').fadeOut(config.changeSpeed,function(){$(this).remove();});
};
} else if (config.effect=='none') {
$(gallery[counter])
.appendTo($cont);
if($cont.children().length>1){
$cont.children().eq(0).remove();
};
};
// update active class on slide link
if(config.links){
$('.'+uniqueClass+'-active').removeClass(uniqueClass+'-active jshowoff-active');
$('.'+uniqueClass+'-slidelinks a').eq(counter).addClass(uniqueClass+'-active jshowoff-active');
};
// reset for html5 objects only
if (isHtml5) {
rmkObj.preload = 'nopreload';
rmkObj.Reset();
}
};// end function transistionTo
// is the rotator currently in 'play' mode
function isPlaying(){
return $('.'+uniqueClass+'-play').hasClass('jshowoff-paused') ? false : true;
};
// start slide rotation on specified interval
function play(src) {
if (!finalStop) {
if (!isBusy()) {
counter++;
transitionTo(gallery, counter);
if (src == 'hover' || !isPlaying()) {
//htmlRotatorTimer = setInterval(function(){ play(); },config.speed);
clearTimeout(htmlRotatorTimer);
htmlRotatorTimer = setTimeout(function(){
play();
}, config.speed);
}
if (!isPlaying()) {
$('.' + uniqueClass + '-play').text(config.controlText.pause).removeClass('jshowoff-paused ' + uniqueClass + '-paused');
}
};
};
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我相信你在transitionTo函数中对play的调用是错误的。你没有提供论据。顺便问一下,为什么还要在外面调用 play() 呢?如果可以的话,请贴出完整的代码。我不确定您为什么将计数器字符串传递给transitionTo。一种建议是在 play 方法中使用 setInterval 方法,如下所示
I believe that your call to play is wrong inside the transitionTo function. You are not supplying an argument. By the way, why do you call play() outside as well? If possible, please post the entire code. I'm not sure why you're passing counter string to transitionTo. One suggestion is to use setInterval method in play method like this