Javascript 脚本中的延迟不起作用

Javascript 脚本中的延迟不起作用,javascript,html,datetime,canvas,timer,Javascript,Html,Datetime,Canvas,Timer,我有一个javascript中的sleep函数对象- function sleep(ms) { var d = new Date(); var target=d.getTime()+ms; var next = d; console.log('Slept'); while(next.getTime()<=target) { next=new Date();

我有一个javascript中的sleep函数对象-

    function sleep(ms) { 
        var d = new Date(); 
        var target=d.getTime()+ms; 
        var next = d; 
        console.log('Slept');
        while(next.getTime()<=target) {
            next=new Date(); 
        }
        console.log('Woke Up');
        return;
    }
5秒后

Woke Up
此代码也可以正常工作-
alert('foo');睡眠(5000);警报(“条”)
首先
foo
,5秒后
bar

但是这个函数

//ctx is a 2d context of a canvas
function go() {
    ctx.fillRect(100,100,200,200); 
    sleep(1000); 
    ctx.fillRect(200,200,300,300); 
    sleep(1000);
    ctx.fillRect(300,300,400,400); 
    sleep(1000);
    ctx.fillRect(400,400,500,500);
}

go();
它不起作用。我的意思是它正在工作,但不是它应该的方式。首先,控制台显示-

Slept
//1 second later
Woke Up  
//1 second later  
Slept
//1 second later
Woke Up
Slept
//1 second later
Woke Up
在打印完所有这些信息后,图形(矩形)被绘制在画布上。 有没有办法不用
setTimeout
setInterval
来完成这项工作

问题-为什么
fillRect
不能使用我的
睡眠
功能?
是否有一种方法可以在不使用
setTimeout
setInterval
的情况下延迟javascript中的某些代码?

您必须将sleep()函数实现为异步(即setTimeout()或setInterval())。按照您的方式,它会阻止浏览器的所有操作,例如渲染和绘制;只有在将控件返回到浏览器后,才会绘制矩形。

“有没有办法不用
setTimeout
setInterval
来完成此操作?”没有,没有。您需要将每个步骤之间的间隔设置为异步,计时器就是这样

问题是,只要
sleep(…)
正在运行,它就会阻塞UI线程。在再次释放之前,浏览器无法使用正在绘制的形状更新显示

即使执行中断1毫秒,也有足够的时间在两个步骤之间进行更新:

function go() {
    ctx.fillRect(100,100,200,200);
    sleep(1000);
    ctx.fillRect(200,200,300,300);
    sleep(1000);
    setTimeout(function () {
        ctx.fillRect(300,300,400,400);
        sleep(1000);
        ctx.fillRect(400,400,500,500);
    }, 1);
}

“有没有不使用setTimeout或setInterval的方法来完成此操作?”有没有特定的原因使您不能或不想使用它们?计时器通常是延迟代码执行的首选方式,因为它们允许其他代码/事件在此期间继续运行。@JonathanLonowski我避免使用计时器,因为需要执行一系列操作。将它们放在回调中,然后在满足特定条件后使用
clearTimeout
会变得非常混乱。当画布方法与
alert
配合良好时,为什么不能与之配合使用呢?@Sandyle像
alert
这样的对话框实际上是由浏览器的开发人员决定的——它们不是真正标准化的。但是,通常情况下,您会看到它们工作,因为它们有自己的线程,并暂停UI线程,直到它们被解除。另一方面,
完全依赖于执行JavaScript和管理UI的同一线程。因为alert()也以阻塞方式工作-它会立即中断js线程。
function go() {
    ctx.fillRect(100,100,200,200);
    sleep(1000);
    ctx.fillRect(200,200,300,300);
    sleep(1000);
    setTimeout(function () {
        ctx.fillRect(300,300,400,400);
        sleep(1000);
        ctx.fillRect(400,400,500,500);
    }, 1);
}