闭包中的clearTimeout

时间:2012-08-11 12:47:16

标签: javascript jquery

我创建了一个具有以下结构的jquery插件:

(function($){

var timer_handle, i = 5 ;

 $.my_plugin = function(){
  return{
    // provide $.my_plugin.reset() public method to reset
    reset : function(){ clearTimeout(timer_handle); }
  }
}();

 $.fn.my_plugin = function(){

    // init codes ...

    function tick(){
      i -= 1;
      console.log(i+'sec elapsed');
      if(i == 0){
      console.log('time over');   
      $.my_plugin.reset();
      }
        timer_handle = setTimeout(tick, 1000);
    }
    tick();
 }
 })(jQuery);

$('body').my_plugin();

当我在控制台看到,经过0秒后,计数器仍然以负数运行, 即尚未清除setTimeout。 正如我所研究的那样,公共方法 $ .my_plugin.reset();从外面打电话清除计时器, 但是在勾选内部调用的$ .my_plugin.reset()不会清除计时器。

这种情况的解决方案可能是什么?????

1 个答案:

答案 0 :(得分:0)

因为您正在内部 $.my_plugin.reset();函数中调用tick(),所以无法清除超时。先前计划的超时已经发生,这就是tick()正在执行的原因。 (这与代码是否在闭包中无关。)

相反,如果i已达到0,则不要设置下一次超时:

function tick(){
  i -= 1;
  console.log(i+'sec elapsed');
  if(i == 0){
    console.log('time over');
  } else {
    timer_handle = setTimeout(tick, 1000);
  }
}

如果您要从 $.my_plugin.reset(); 之外的其他代码调用tick(),那么会有一个未完成的超时,可以清除它会阻止tick()再次运行。

请注意,声明您的timer_handlei变量会立即调用匿名函数意味着对您的插件的所有调用都将访问这些相同的变量,因此如果针对更多插件运行插件,您将获得不正确的行为而不是同时在页面上的一个元素。