使用setInterval创建一个可以自行清理的计时器?

时间:2011-10-07 15:19:43

标签: javascript

我想使用setInterval来动画一些东西。首先,我希望能够指定一系列页面元素,并让它们设置背景颜色,这将逐渐淡出。一旦颜色恢复正常,就不再需要定时器。

所以我有

function setFadeColor(nodes) {
  var x = 256;
  var itvlH = setInterval(function () {
    for (i in nodes) {
      nodes[i].style.background-color = "rgb(0,"+(--x)+",0);";
    }
    if (x <= 0) {
      // would like to call 
      clearInterval(itvlH);
      // but itvlH isn't in scope...?
    }
  },50);
}

进一步复杂化的情况是,我希望能够有多个这样的实例。我想也许我会将现场间隔处理程序推入阵列并在它们“死亡”时将它们清理干净,但我怎么知道它们何时发生?只有在间隔闭合内,我才知道它何时完成。

如果有办法从闭包内获取区间的句柄,那将会有什么帮助。

或者我可以做这样的事情?

function intRun() {
  for (i in nodes) {
    nodes[i].style.background-color = "rgb(0,"+(--x)+",0);";
  }
  if (x <= 0) {
    // now I can access an array containing all handles to intervals
    // but how do I know which one is ME?
    clearInterval(itvlH);
  }
}
var handlers = [];
function setFadeColor(nodes) {
  var x = 256;
  handlers.push(setInterval(intRun,50);
}

4 个答案:

答案 0 :(得分:1)

您的第一个示例将正常工作,花花公子^ _ ^

function setFadeColor(nodes) {
  var x = 256;
  var itvlH = setInterval(function () {
    for (i in nodes) {
      nodes[i].style.background-color = "rgb(0,"+(--x)+",0);";
    }
    if (x <= 0) {
      clearInterval(itvlH);
      // itvlH IS in scope!
    }
  },50);
}

你有没有测试过它?

答案 1 :(得分:0)

我认为您可以使用一个小技巧来存储处理程序。先做一个对象。然后将处理程序设置为属性,稍后访问该对象的属性。像这样:

function setFadeColor(nodes) {
  var x = 256;
  var obj = {};

  // store the handler as a property of the object which will be captured in the closure scope
  obj.itvlH = setInterval(function () {
    for (i in nodes) {
      nodes[i].style.background-color = "rgb(0,"+(--x)+",0);";
    }
    if (x <= 0) {
      // would like to call 
      clearInterval(obj.itvlH);
      // but itvlH isn't in scope...?
    }
  },50);
}

答案 2 :(得分:0)

我使用的代码就像你的第一个块一样,它运行正常。此jsFiddle也适用。

答案 3 :(得分:0)

您可以像这样编写辅助函数:

function createDisposableTimerInterval(closure, delay) {
    var cancelToken = {};
    var handler = setInterval(function() {
        if (cancelToken.cancelled) {
            clearInterval(handler);
        } else {
            closure(cancelToken);
        }
    }, delay);
    return handler;
}

// Example:

var i = 0;
createDisposableTimerInterval(function(token) {
    if (i < 10) {
        console.log(i++);
    } else {
        // Don't need that timer anymore
        token.cancelled = true;
    }
}, 2000);