强制从递归函数

时间:2016-05-12 07:24:35

标签: javascript jquery html5 canvas

我想创建一个自定义进度条。但是我使用递归函数为其更新数据,我无法更新进度条中的画布。

以下是我的代码的一部分:

var length = 0;

recursiveFunction = function(){
   length++;
   updateLength(length);
   //some work
   recursiveFunction();
}

updateLength = function(length){
   setLength(length);
}

setLength(length){
    var c = document.getElementById(canvas);
    var ctx = c.getContext("2d");
    ctx.fillStyle = "#fc0";
    ctx.fillRect(0, 0, length, 10);
}

所有这些函数都在不同的JS文件和不同的类中。

问题是画布没有在setLength函数中重绘。

1 个答案:

答案 0 :(得分:2)

这与JavaScript是单线程有关,当时只能做一件事。只要该代码正在运行,其他所有内容(例如更新到屏幕)都必须等待。

为了解决这个问题,您可以在代码中引入一些异步性,暂停代码,以便更新屏幕。

例如(注意:如果不执行其他更改,此更改本身可能无效):

recursiveFunction = function(){
   length++;
   updateLength(length);
   //some work
   requestAnimationFrame(recursiveFunction);  // makes call async
}

该函数现在将结束,但会添加一个事件以供将来使用(在这种情况下通常为16.7ms)。同时画布可以更新为屏幕。

但当然不是没有问题。上下文正在改变,因为它是一个递归函数,你可能想传入参数。虽然帖子中没有显示哪些内容(如果有的话),但您可以使用requestAnimationFrame()代替setTimeout()来传递参数。如果您依赖上下文(例如bind()),也可以使用this

// example of bind
requestAnimationFrame(recursiveFunction.bind(this));

setTimeout() can take more arguments比延迟:

setTimeout(recursiveFunction.bind(this), 17, arg1, arg2, arg3, ...);

另一种方法是使用 Web Workers 。这将允许您在单独的线程上尽可能快地运行代码,并偶尔向主机发送一条消息,其中包含到目前为止的进度,这将允许独立更新画布。如果函数长时间运行,这是推荐的路径。 Web worker有good support但不适用于旧的IE或Opera Mini。