2011-04-24 89 views
0

我有一个脚本,它在画布上绘制了一堆线条,但是它非常强烈,所以渲染会在几秒内冻结浏览器。我添加了setTimeout(),以便浏览器不会冻结,并且它有效地混淆了我的脚本。这是很难解释如何,所以我有两个在线的例子:递归函数和setTimeout()问题

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

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

注意,我只在整个脚本改变单一的线即线69:
而不的setTimeout():vLoop();
用的setTimeout():setTimeout(vLoop,1);

+0

你能告诉我们'vLoop'的实际代码吗 – Raynos 2011-04-24 13:31:05

回答

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); 
} 

最后一块是确保象限没有跨越彼此的地方。

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引用和混乱的全局状态,你的整个程序中断。

+0

他们仍然是单线程的,所以说他们并行运行并不是很准确。 – 2011-04-24 13:37:40

+0

@NickCraver时间拼接执行是它们实际上并行运行。如何使用setTimeout与时间拼接不同? – Raynos 2011-04-24 13:56:20

+0

@Raynos - 你永远不会在同一时间内多次使用该方法,这是平行的定义:) – 2011-04-24 14:19:05

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

+0

这只是延迟整个绘图过程,直到后来。只要块开始运行,您仍然有冻结浏览器的原始问题。 – musaul 2011-04-26 00:36:29

+0

@Musaul - 它会在一个定时回调中,但是你可以通过一个非0值的超时持续时间来减轻它的影响,例如把它乘以'i'。 – 2011-04-26 00:43:55