jQuery函数使用包含setTimeout的每个循环调用自身,而不是在结束时发生

时间:2014-12-04 21:34:34

标签: javascript jquery

我正在一个需要在表格中在线滚动用户列表的项目。这个想法是服务器被ping到整个列表,它填充前5个然后删除顶部并在2.5秒间隔添加下一个。整个列表完成后,我需要点击服务器获取最新列表并永远重复。

我遇到的问题是“永远”的问题。虽然第一次加载很好并且循环工作很好,但第二次加载有问题。如果// get_users_online_today();取消注释,看起来好像在第一个setTimeout()触发器完成后调用发生。

我似乎无法弄清楚将函数放在函数内的位置,以便重复调用它。

$(function(){
   function get_users_online_today(){
      var user = 0;

      $.ajax({
         url: 'ajax.php',
         data: {action: 'Users Online Today'},
         dataType: 'json'
      }).done(function(users){
         $.each(users, function(index, details){
            if($('#users_online_today tbody tr').length <= 5){
               $('#users_online_today tbody').append('<tr><td>' + details.name + '</td></tr>');
            }else{
               setTimeout(function(){
                  $('#users_online_today tbody tr:first').remove();
                  $('#users_online_today tbody').append($('<tr><td>' + details.name + '</td></tr>').fadeIn(250));
               }, (user++) * 2500);
            }
         });

         //get_users_online_today();
      });
   }

   get_users_online_today();
});

1 个答案:

答案 0 :(得分:0)

在setTimeout周围添加一个闭包,以便它正确引用你在循环中的用户应该可以解决你的问题。现在代码中发生的事情是,当setTimeout实际发生时,它会查看先前作用域的“用户”(最后一个用户),而不是包含正确值的本地范围变量。

(function(i, d){
  setTimeout(function(){
    $('#users_online_today tbody tr:first').remove();
    $('#users_online_today tbody').append($('<tr><td>' + d.name + '</td></tr>').fadeIn(250));
  }, (i + 1) * 2500);
}(index, details));

您也不需要该用户变量,因为您在.each()函数中传递了用户的索引。除非你出于其他原因使用它,否则只需在超时功能之前/之后将其设置为+ = 1。

这里有一个更好的解释,关闭是什么以及它们有用的原因: How do JavaScript closures work?