如果丢失调用对象,如何杀死setInterval()/ setTimout()? [英] How do I kill a setInterval()/setTimout() if I lose the calling object?

查看:174
本文介绍了如果丢失调用对象,如何杀死setInterval()/ setTimout()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个相当大的应用程序,因此我需要在特定时间间隔内再次按下一个键来再次调用一个函数。该应用程序的某些部分我无法编辑,但它替代了.onkeyup()侦听器,有时该间隔会永远保留在那里。我真正想要的是当对象被销毁,重新分配等时停止的时间间隔...在setInterval(),绑定,闭包之后,我进行了尝试,现在我什至更加困惑:

I'm working on a rather large app, I need to call a function over an over again while a key is being pressed, at a specific interval. There's parts of the app that I can't edit, but it's replacing my .onkeyup() listeners and sometimes the interval is just left there forever. What I really want is for the interval to stop when the object gets destroyed, reassigned, etc... After setInterval(), bindings, closures, I made this to try something out and now I am even more confused:

function myInterval(){
    this.name = 'Paul'
    that=this;
this.go = function go(){
        if(that){
            this.interval = setTimeout(function(){
                console.log(that.name);
                that.go();
            },100);
        };
        console.log(that.name);
    };
};

periodic = new myInterval();
periodic.go();
setTimeout(function(){
    periodic.name='George';
}, 200);
setTimeout(function(){
    periodic.name ='John';
    periodic.go = '';
    periodic.name = 'Ringo'
}, 300);

输出:

Paul
Paul
Paul
George
George
Ringo 
> Uncaught TypeError: Property 'go' of object #<myInterval> is not a function

因此,重新分配该函数有效,但是如果我替换

So, reassigning the function works, but if I replace

periodic.go = '';

periodic = '';

我知道了

Paul
Paul
Paul
George
George
John
John
...

以此类推。间隔永远不会停止...

And so on forverer; The interval never stops...


  1. 有人可以解释吗?

  1. Can anyone explain?

是否有一个通用,优雅的解决方案来确保我不会将运行间隔丢入以太坊?

Is there a common, elegant solution to ensuring I don't go dropping running intervals into the aether?


推荐答案



间隔永远不会停止...谁能解释?

The interval never stops...Can anyone explain?


闭包范围内的变量是其原因,下面的代码将在将o设置为null的同一范围内使用变量o。

Variables trapped in closure scope is the reason for that, the following code will use variable o in same scope that sets o to null.

注意:我更喜欢使用闭包创建器来限制范围并防止其他意外情况。

Note: I prefer to use closure creators to limit scope and prevent other surprises. The following will create closures on they fly to keep code simple.

var o = {};
setTimeout(function(){//closure accessing o directly
   console.log("why is o null here:",o);
},100);
o=null;

以下代码将使用o作为传递的o,传递的o现在被困在创建的闭包范围中,并且将o设置为null不会影响传递的o。突变o(o.something = 22)将影响传递的o。 (Google使用按值引用JavaScript)

The following code will use o as passed o, passed o is now trapped in the created closure scope and setting o to null does not affect passed o. Mutating o (o.something=22) will affect passed o. (google "javascript by reference by value" for references)

var o = {};
setTimeout((function(o){
  return function(){//closure accessing passed o
   console.log("why is o not here:",o);
  };
}(o)),100);
o=null;

要解决创建closurs的循环中的常见问题,请将变量(i)传递给返回的函数闭包

To solve a common problem in loops creating closurs you pass the variable (i) to a function that returns a closure

for(var i = 0;i<10;i++){
  setTimeout((function(i){
    return function(){//not using i in the for loop but the passed one
     console.log("and i is:",i);//0 to 9
    };
  }(i)),100);
}

因为将i变量设为与闭包相同的作用域,将使您不必要结果:

Because having the i variable in the same scope as the closure will give you unwanted results:

for(var i = 0;i<10;i++){
  setTimeout(function(){
    console.log("and i is:",i);//10 times and i is: 10
  },100);
}

为什么periodic.go =作品与通过参考价值。以下代码显示了工作原理:

Why periodic.go="" works has something to do with the pass by value by reference. How that works is shown in the following code:

function test(o){
  o=22;//no mutation but an assignment
}
var o = {name:"me"};
test(o);
console.log(o);//Object { name="me" }

function test2(o){
  o.name="you";//mutates
}
test2(o);
console.log(o);//Object { name="you"}

如何解决

我对代码进行了一些更改,以利用共享成员的原型(go函数)并创建闭包确保关闭的范围限于您实际需要的位置。

I've changed your code a little to take advantage of protype for shared members (the go function) and create closures to make sure the scope of the closure is limited to what you actually need to be in there.

有关更多详细信息,请阅读构造函数和this变量简介

For more details read the introduction to constructor function and the this variable.

function MyInterval(){//capitalize constructor
    this.name = 'Paul';
    this.doContinue = true;
    this.timeoutid = false;
};
MyInterval.prototype.closures ={//creates closures with limited scope
  //closure for the go function setting the invoking object
  go:function(me){
    return function(){
      console.log("In go, name is:",me.name);
      me.go();
      //de reference "me", we no longer need it
      // can't do this in a setInterval though
      me=null;
    };
  }
}
MyInterval.prototype.go = function(){
  if(this.constructor===MyInterval){
    //if you were to call go multiple times
    if(this.timeoutid)
      clearTimeout(this.timeoutid);
    //do it again if this.doContinue is true
    this.timeoutid = (this.doContinue)? setTimeout(
      this.closures.go(this)
      //creates a closure function
      ,100
    ):false;
    return;
  };
  console.log("this is not the correct value:",this);
};
//added stop, good call from shadow, now you can stop immediately
//  or set doContinue to false and let it run it's course
MyInterval.prototype.stop = function(){
  if(this.timeoutid)
    clearTimeout(this.timeoutid);
  this.timeoutid=false;
};

periodic = new MyInterval();
periodic.go();
//because the clearTimeout you can accedentally do something silly like:
periodic.go();
periodic.go();
setTimeout(function(){
    periodic.name='George';
}, 150);
setTimeout(function(){
    periodic.name ='John';
    periodic.doContinue = false;
    periodic.name = 'Ringo'
}, 250);

这篇关于如果丢失调用对象,如何杀死setInterval()/ setTimout()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆