window.onload = ->
boxOrig1 = 10
boxOrig2 = 30
canvasW = 400
canvasH = 300
ctx = $("#canvas")[0].getContext('2d');
draw = (origin,dimension) ->
ctx.clearRect(0, 0, canvasW, canvasH)
ctx.fillStyle = 'rgb(200,0,0)'
ctx.fillRect(origin + boxOrig1, boxOrig1, dimension, dimension)
ctx.fillStyle = 'rgba(0, 0, 200, 0.5)'
ctx.fillRect(origin + boxOrig2, boxOrig2, dimension, dimension)
for m in [10..100] by 10
t = setTimeout (-> draw(m, 150)), 1000
t.clearTimeout
# draw(m,150)
# alert m作为练习,上面的代码旨在在画布上绘制一个小设计,暂停一秒钟,然后向右重新绘制10个像素。
我可以看到,当我用警报中断循环时,机制工作得很好(就像在最后两个注释行中一样),但是我没有使用setTimeout函数获得预期的行为。设计只是在超时后出现在最右边的位置,跳过了中间的增量步骤。
我从其他例子中尝试了许多不同的方法来做这件事,但它只是融化了我的大脑。有什么建议吗?
发布于 2011-11-30 08:00:55
Geoff概述了一种方法(使用setInterval并从回调中清除它),因此我将概述另一种方法:从回调中使用setTimeout。就像这样
m = 10
do drawCallback = ->
draw m, 150
m += 10
setTimeout drawCallback, 1000 unless m > 100请注意,这两种方法之间有一个细微的时序差异,您应该知道:setInterval func, 1000将每1000ms运行一次函数;链式setTimeout将在每次函数调用之间设置1000ms的延迟。因此,如果draw花了100ms,那么链接的setTimeout将等同于setInterval func, 1100。这可能无关紧要,但值得注意。
奖励方法:你不必放弃你的循环;你可以一次设置所有的超时:
for m in [10..100] by 10
do (m) ->
setTimeout (-> draw(m, 150)), 100 * mdo (m)是必需的,这样传递给setTimeout的闭包才能看到m的每个值,而不仅仅是它在循环中的最终值。有关这方面的更多信息,请参阅我的文章A CoffeeScript Intervention。
Finally:我知道这一切一开始看起来很混乱,但JS中的计时实际上非常简单,因为该语言是单线程的。这意味着您使用setTimeout或setInterval或任何其他异步函数调度的事件在循环期间永远不会发生,即使循环是无限的。它们只有在所有代码执行完毕后才会发生。我将在my book on CoffeeScript中更详细地讨论这一点。
https://stackoverflow.com/questions/8318796
复制相似问题