递归函数和setTimeout()问题

时间:2011-04-24 13:29:32

标签: javascript canvas settimeout

我有一个脚本在画布上画了一堆线,但它非常强烈,所以在渲染冻结浏览器几秒钟时。我添加了setTimeout(),以便浏览器不会冻结,它有效地搞砸了我的脚本。很难解释如何,所以我在网上有两个例子:

没有setTimeout():http://www.modwebsolutions.com/test1

使用setTimeout():http://www.modwebsolutions.com/test2

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

3 个答案:

答案 0 :(得分:3)

正如其他人所暗示的那样,这里的问题是你一次只画一个象限。一旦调用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 );
}

最后一个区块确保象限不会相互踩踏。

答案 1 :(得分:0)

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个引用并混乱全局状态并且整个程序都会中断。

答案 2 :(得分:0)

正在发生的事情是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);
});

然后这会起作用(但这很危险,订单并非绝对有用!)

You can see a working example here