递归函数和setTimeout()问题
我有一个脚本可以在画布上绘制一堆线条,但它非常密集,因此渲染时浏览器会冻结几秒钟。我添加了 setTimeout() ,这样浏览器就不会冻结,并且它实际上弄乱了我的脚本。很难解释如何操作,所以我在网上有两个例子:
没有 setTimeout() : http://www.modwebsolutions.com /test1
使用 setTimeout() : http://www.modwebsolutions.com/test2
请注意,我只更改了整个脚本中的一行,即第 69 行:
不使用 setTimeout():vLoop();
使用 setTimeout():setTimeout(vLoop,1);
I have a script that draws a bunch of lines on canvas, but it's pretty intense so while rendering freezes browser for a few seconds. I added setTimeout() so that the browser wouldn't freeze and it effectively messed up my script. It's difficult to explain how, so I have two examples online:
Without setTimeout() : http://www.modwebsolutions.com/test1
With setTimeout() : http://www.modwebsolutions.com/test2
Note, that I only change a single line in the whole script, that is line 69:
without setTimeout(): vLoop();
with setTimeout(): setTimeout(vLoop,1);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如其他人所暗示的,这里的问题是您一次绘制一个象限的线。一旦调用
SetTimeout
方法并且第一个vLoop
返回,代码就会继续运行到下一个drawVertical
,这将更改所有全局变量等等。您需要做的是同步调用 vLoop 的方式以及更改全局变量的方式。
这基本上是解决方案:
将 ...
... 替换为
...
将您的
drawVertical
函数替换为...
将
vLoop
函数原型更改为如下所示...
最后将递归
vLoop
调用(从 vLoop 内)替换为 ...最后一个块是确保象限不会相互跨越的地方。
The problem here, as hinted at by others, is that you are drawing the lines a quadrant at a time. As soon as the
SetTimeout
method is called and the firstvLoop
returns, the code carries on running into the nextdrawVertical
which changes all the global variables and so on.What you need to do is synchronise how you're calling vLoop and how you are changing the globals.
This is basically the solution:
Replace ...
... with ...
Replace your
drawVertical
function with ...change the
vLoop
function prototype to look like this ...and finally replace your recursive
vLoop
call (from within vLoop) with ...The last block is where it ensures that the quadrants are not stepping over each other.
您一次调用
vLoop
的 4 个递归函数。这里的问题是 setTimeout 是非阻塞的,而递归是阻塞的。所以基本上现在所有 4 个drawVertical 函数都是并行运行的,而不是按顺序运行。另一个问题是所有 4 个引用都会扰乱全局状态,导致整个程序崩溃。
Your calling 4 recursive functions of
vLoop
at once. The problem here is thatsetTimeout
is non-blocking where as recursion is blocking. So basically you now have all 4 of these drawVertical functions running in parallel rather then in sequence.The other problem is that all 4 refer and mess with global state and your entire program breaks.
所发生的情况是
setTimeout()
将所有执行延迟到稍后。不幸的是,此时您的全局变量已全部从初始循环移动到其结束位置,因为它在绘制第一条线之前完成。如果您将超时进一步提高(因此您正在使用的共享变量在绘制时间之前不会受到影响),您可以实现您所追求的目标,例如:
那么这将起作用(但这很危险,顺序并不绝对)保证!)
您可以在此处查看一个工作示例。
What's happening is what
setTimeout()
delays all that execution until later. Unfortunately, by that point your global variables have all moved to their ending positions from the initial loop, since it completed before the first line was drawn.If you moved your timeout further up (so the shared variables you're using aren't affected until draw time) you could achieve what you're after, for example:
Then this would work (but it's dangerous, order isn't absolutely garunteed!)
You can see a working example here.