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



我想使用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);
}

使情况更复杂的是,我希望能够有多个这样的实例。我在想也许我会把活动间隔处理程序推到一个数组中,并在它们"死亡"时清理它们,但是我怎么知道它们什么时候会这样做呢?只有在interval闭包中,我才知道它何时完成。

如果有一种方法可以从闭包中获得interval的句柄,那将会有所帮助。

或者我可以这样做?

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);
}

你的第一个例子将会运行良好^_^

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);
}

你有没有测试过?

我已经使用了像您的第一个块一样的代码,它工作得很好。这个jsFiddle也可以用

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

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);
}

你可以这样写辅助函数:

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);

最新更新