Javascript 递归函数和setTimeout()问题

Javascript 递归函数和setTimeout()问题,javascript,canvas,settimeout,Javascript,Canvas,Settimeout,我有一个脚本在画布上画了一堆线,但它非常紧张,所以在渲染时会将浏览器冻结几秒钟。我添加了setTimeout(),这样浏览器就不会冻结,它实际上会弄乱我的脚本。这很难解释,所以我在网上有两个例子: 不带setTimeout(): 使用setTimeout(): 请注意,我只更改了整个脚本中的一行,即第69行: 没有setTimeout():vLoop() 使用setTimeout():setTimeout(vLoop,1) 您可以同时调用vLoop的4个递归函数。这里的问题是,setTimeou

我有一个脚本在画布上画了一堆线,但它非常紧张,所以在渲染时会将浏览器冻结几秒钟。我添加了setTimeout(),这样浏览器就不会冻结,它实际上会弄乱我的脚本。这很难解释,所以我在网上有两个例子:

不带setTimeout():

使用setTimeout():

请注意,我只更改了整个脚本中的一行,即第69行:
没有setTimeout():
vLoop()
使用setTimeout():
setTimeout(vLoop,1)

您可以同时调用
vLoop
的4个递归函数。这里的问题是,
setTimeout
是非阻塞的,而as递归是阻塞的。所以基本上你现在有了4个并行运行的函数,而不是顺序运行的函数

另一个问题是,所有4个引用并扰乱全局状态,导致整个程序中断

您可以同时调用
vLoop
的4个递归函数。这里的问题是,
setTimeout
是非阻塞的,而as递归是阻塞的。所以基本上你现在有了4个并行运行的函数,而不是顺序运行的函数


另一个问题是,所有4个都引用并弄乱了全局状态,导致整个程序中断。

发生的是
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);
});
那么这就行了(但这很危险,秩序并不是绝对的夸夸其谈!)


。不幸的是,到那时,您的全局变量都从初始循环移动到了它们的结束位置,因为它在绘制第一条线之前就完成了

如果您将超时时间进一步向上移动(这样您使用的共享变量在绘图时间之前不会受到影响),您可以实现您所追求的目标,例如:

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);
});
那么这就行了(但这很危险,秩序并不是绝对的夸夸其谈!)


.

正如其他人所暗示的,这里的问题是,你一次画一个象限的线。只要调用了
SetTimeout
方法,并且第一个
vLoop
返回,代码就会继续运行到下一个
drawVertical
,从而更改所有全局变量,依此类推

你需要做的是同步你如何调用vLoop和你如何改变globals

这基本上就是解决方案:

替换

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\uuu0)和&(xStart\uuu0

最后一块是确保象限不会相互重叠的地方。

正如其他人所暗示的,这里的问题是,您一次画一个象限的线。只要调用了
SetTimeout
方法,并且第一个
vLoop
返回,代码就会继续运行到下一个
drawVertical
,从而更改所有全局变量,依此类推

你需要做的是同步你如何调用vLoop和你如何改变globals

这基本上就是解决方案:

替换

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\uuu0)和&(xStart\uuu0

最后一块是确保象限不会相互重叠的地方。

你能告诉我们
vLoop
的实际代码吗
vLoop
的实际代码仍然是单线程的,所以说它们并行运行并不准确。@NickCraver时间拼接执行实际上是它们并行运行。使用setTimeout与时间拼接有何不同?@Raynos-您永远不会在同一时间多次进入该方法,这是parallel:)@NickCraver的定义,但您将在递归执行的函数集中一次以上。单个函数不会并行运行,但递归执行会并行运行。@Raynos-它不会…在任何情况下,他正在运行的任何代码行都不会同时运行。它们仍然是单线程的,所以说它们并行运行并不准确。@NickCraver Time拼接执行实际上是并行运行的。使用setTimeout与时间拼接有何不同?@Raynos-您永远不会在同一时间多次进入该方法,这是parallel:)@NickCraver的定义,但您将在递归执行的函数集中一次以上。单个函数不会并行运行,但递归执行会并行运行。@Raynos-它不会…在任何时候,他运行的任何代码行都不会同时运行,这只是将整个绘图过程推迟到以后。一旦块开始运行,您仍然存在冻结浏览器的原始问题。@Musaul-It'l