递归函数和setTimeout()问题

发布于 2024-11-03 06:15:33 字数 504 浏览 6 评论 0原文

我有一个脚本可以在画布上绘制一堆线条,但它非常密集,因此渲染时浏览器会冻结几秒钟。我添加了 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

山川志 2024-11-10 06:15:33

正如其他人所暗示的,这里的问题是您一次绘制一个象限的线。一旦调用 SetTimeout 方法并且第一个 vLoop 返回,代码就会继续运行到下一个 drawVertical,这将更改所有全局变量等等。

您需要做的是同步调用 vLoop 的方式以及更改全局变量的方式。

这基本上是解决方案:

 

将 ...

drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);

... 替换为

var q = new Array();
q[0] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y];
q[1] = [c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y];
q[2] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0];
q[3] = [c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0];

drawQuadrant(q, 0);

...

将您的 drawVertical 函数替换为

function drawQuadrant(q, i)
{
    var r = q[i];

    c__ = r[0];
    step__ = r[1];
    stepInt__ = r[2];
    bigStep__ = r[3];
    xStart__ = r[4];
    xEnd__ = r[5];
    yStart__ = r[6];
    yEnd__ = r[7]; 


    vLoop(q,i);
}

...

vLoop 函数原型更改为如下所示

function vLoop(q,i)

...

最后将递归 vLoop 调用(从 vLoop 内)替换为 ...

if ((xStart__ > 0) && (xStart__ < window.innerWidth))
{
    setTimeout( function(){vLoop(q,i)}, 1 );
}
else if (++i < 4)
{
    setTimeout( function(){drawQuadrant(q,i)}, 1 );
}

最后一个块是确保象限不会相互跨越的地方。

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 first vLoop returns, the code carries on running into the next drawVertical 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 ...

drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);

... with ...

var q = new Array();
q[0] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y];
q[1] = [c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y];
q[2] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0];
q[3] = [c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0];

drawQuadrant(q, 0);

 

Replace your drawVertical function with ...

function drawQuadrant(q, i)
{
    var r = q[i];

    c__ = r[0];
    step__ = r[1];
    stepInt__ = r[2];
    bigStep__ = r[3];
    xStart__ = r[4];
    xEnd__ = r[5];
    yStart__ = r[6];
    yEnd__ = r[7]; 


    vLoop(q,i);
}

 

change the vLoop function prototype to look like this ...

function vLoop(q,i)

 

and finally replace your recursive vLoop call (from within vLoop) with ...

if ((xStart__ > 0) && (xStart__ < window.innerWidth))
{
    setTimeout( function(){vLoop(q,i)}, 1 );
}
else if (++i < 4)
{
    setTimeout( function(){drawQuadrant(q,i)}, 1 );
}

The last block is where it ensures that the quadrants are not stepping over each other.

梦晓ヶ微光ヅ倾城 2024-11-10 06:15:33
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);

您一次调用 vLoop 的 4 个递归函数。这里的问题是 setTimeout 是非阻塞的,而递归是阻塞的。所以基本上现在所有 4 个drawVertical 函数都是并行运行的,而不是按顺序运行。

另一个问题是所有 4 个引用都会扰乱全局状态,导致整个程序崩溃。

drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y);
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);

Your calling 4 recursive functions of vLoop at once. The problem here is that setTimeout 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.

ぇ气 2024-11-10 06:15:33

所发生的情况是 setTimeout() 将所有执行延迟到稍后。不幸的是,此时您的全局变量已全部从初始循环移动到其结束位置,因为它在绘制第一条线之前完成。

如果您将超时进一步提高(因此您正在使用的共享变量在绘制时间之前不会受到影响),您可以实现您所追求的目标,例如:

setTimeout(function() {
    drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y);
    drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y);
    drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0);
    drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);
});

那么这将起作用(但这很危险,顺序并不绝对)保证!)

您可以在此处查看一个工作示例

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:

setTimeout(function() {
    drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y);
    drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y);
    drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0);
    drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0);
});

Then this would work (but it's dangerous, order isn't absolutely garunteed!)

You can see a working example here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文