我正在我的网站上实现一个趋势功能,并且想知道在递归函数中处理用户点击事件的最佳方法。
代码示例:
var trendingCodes = [];
// trendingCodes is json populated by ajax, this part works fine and not included for brevity
// looks like {code:'SadPanda', text:'Thanks for checking out my !shouttag', img:false}
// Kick this pig
showTrendingCode(0, 200);
function showTrendingCode(indexCurrent, fadeSpeed)
{
var indexNext = ((indexCurrent + 1) % trendingCodes.length);
var trendingCode = trendingCodes[indexCurrent];
if (trendingCodes.length > 1) {
// !!!! Problem
// I am trying to register an event handler for the 'next' trending code
// but if I click multiple times it causes a 'maximum stack exceeded' error
jQuery('#trending-refresh').off().on('click', function()
{
showTrendingCode(indexNext, 200);
});
jQuery('#trending-text p').add(jQuery('#trending-title span')).add(jQuery('#trending-refresh')).fadeIn(fadeSpeed);
setTimeout(function () { showTrendingCode(indexNext, 600); }, 5000);
}
}
如您所见,我正在尝试为 dom 元素注册一个事件处理程序(下一步),但是如果用户多次单击该链接,我会收到“超出最大堆栈”错误。如果用户根本没有点击,那么该功能将正常运行(永久运行,这是预期的效果)。
有什么建议可以让这项工作按预期进行吗?
这是 fiddle :https://jsfiddle.net/o1ekr6g3/
最佳答案
尝试创建一个变量来引用超时(如果已定义),使用 .stop()
和 clearTimeout()
,将 .one()
替换为.on()
var timeout = null;
showTrendingCode(0, 400);
function showTrendingCode(indexCurrent, fadeSpeed) {
if (timeout) {
clearTimeout(timeout);
$("*").stop()
}
var indexNext = ((indexCurrent + 1) % trendingCodes.length);
var trendingCode = trendingCodes[indexCurrent];
jQuery('#trending-text p').add(jQuery('#trending-title span')).fadeOut(fadeSpeed, function() {
if (trendingCode.code) {
jQuery('#trending-title span').html('<a href="/!/' + trendingCode.code + '">!' + trendingCode.code + '</a>');
jQuery('#trending-text p').text(trendingCode.text);
jQuery('#trending-moneyshot').attr('href', '/!/' + trendingCode.code);
if (trendingCodes.length > 1) {
jQuery('#trending-refresh').off("click").one('click', function() {
clearTimeout(timeout);
$("*").stop(true, true);
showTrendingCode(indexNext, 200);
return true;
});
jQuery('#trending-text p').add(jQuery('#trending-title span')).add(jQuery('#trending-refresh')).fadeIn(fadeSpeed);
timeout = setTimeout(function() {
showTrendingCode(indexNext, 600);
}, 1000);
} else {
jQuery('#trending-text p').add(jQuery('#trending-title span')).fadeIn(fadeSpeed);
}
} else {
jQuery('#trending-title span').text('!SADPANDA');
jQuery('#trending-text p').text('Nothing is trending right now...');
jQuery('#trending-text p').add(jQuery('#trending-title span')).fadeIn('slow');
}
});
}
jsfiddle https://jsfiddle.net/o1ekr6g3/1/
编辑、更新
尝试在 showTrendingCode
之外定义 indexNext
;将 .delay()
替换为 setTimeout()
;使用 .promise()
, .then()
, .fail()
;在 showTrendingCode
#trending-refresh
声明 click
事件和处理程序
var trendingCodes = [{
code: 'FOOBAR',
text: 'This is my !shouttag',
img: false
}, {
code: 'SADPANDA',
text: 'This is another !shouttag',
img: false
}];
var elems = jQuery("#trending-text p, #trending-title span, #trending-refresh");
jQuery("#trending-refresh").click(function() {
elems.stop().promise().fail(function() {
showTrendingCode(indexNext, 400)
})
})
var indexNext;
showTrendingCode(0, 400);
function showTrendingCode(indexCurrent, fadeSpeed) {
indexNext = ((indexCurrent + 1) % trendingCodes.length);
var trendingCode = trendingCodes[indexCurrent];
if (trendingCode.code) {
jQuery('#trending-title span').html('<a href="/!/' + trendingCode.code + '">!' + trendingCode.code + '</a>');
jQuery('#trending-text p').text(trendingCode.text);
jQuery('#trending-moneyshot').attr('href', '/!/' + trendingCode.code);
if (trendingCodes.length > 1) {
elems.fadeIn(fadeSpeed).delay(3000)
.promise()
.then(function() {
$(this).fadeOut(fadeSpeed).promise().then(function() {
showTrendingCode(indexNext, fadeSpeed)
})
})
} else {
jQuery('#trending-title span').text('!SADPANDA');
jQuery('#trending-text p').text('Nothing is trending right now...');
jQuery('#trending-text p, #trending-title span').fadeIn('slow');
}
}
}
#trending-text p,
#trending-title span {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="trending-wrap" class="clearfix">
<a id="trending-moneyshot" href="javascript:void(0);">
<img class="pull-left" src="/image/local/global/trending_image_default.png" />
</a>
<div id="trending-text-wrap">
<div id="trending-title" class="spacerBottomMedium">
Trending: <span class="bold"></span>
</div>
<div id="trending-text">
<p></p>
<a id="trending-refresh" href="javascript:void(0);" style="display:none;">
<img class="pull-left" src="http://lorempixel.com/50/50/technics" />
</a>
</div>
</div>
</div>
jsfiddle https://jsfiddle.net/o1ekr6g3/6/
关于Javascript - 递归 - 迭代具有用户跳过能力的json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35487706/