Javascript 脚本中的延迟不起作用
我有一个javascript中的sleep函数对象-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();
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);
}