Javascript - 递归 - 迭代具有用户跳过能力的json

标签 javascript jquery json recursion

我正在我的网站上实现一个趋势功能,并且想知道在递归函数中处理用户点击事件的最佳方法。

代码示例:

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/

相关文章:

javascript - 如何解决state.set is not a function错误?

javascript - 将购物车页面上的更新按钮从输入转换为 Shopify 中的 anchor 链接

javascript - Requirejs jsonp 和未捕获的语法错误 : Unexpected token :

r - 将嵌套的 JSON 文件转换为 R 数据帧

javascript - 让脚本更好。烟雾不够平滑

php - 将常规 Javascript 转换为 jQuery

javascript - 出错时撤消对构造函数范围的修改

javascript - 如何将 html 文件加载到 jquery 选项卡中

javascript - 如何在 JavaScript 中获取根路径?

c# - 将Json序列化为模型