以下代码使用init()
调用setInterval
方法时,会在中心创建一个球。当keydown()
事件被触发时,球在X和Y轴上移动(取决于用户按下的键)。我很难理解的是按下按键时会发生什么。
当按下某个键以更新键值(setInterval
,keyLeft
等)时,keyRight
会停止,然后重新开始并考虑更新后的值
或
密钥事件中的代码是否在setInterval
正在进行时执行?
我已经读过,setInterval
是异步的,而关键事件是同步的,因为Javascript是单线程的,第二个选项是真的,对吧?我真的可以在这个上使用你的知识..
<canvas id="canvas" style="border: 1px solid black" width="400" height="400"></canvas>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
var Ball = {
positionX: 200,
positionY: 200,
keyLeft: false,
keyRight: false,
keyUp: false,
keyDown: false,
init: function() {
this.canvas = document.getElementById('canvas');
this.ctx = this.canvas.getContext('2d');
setInterval(Ball.draw, 10);
},
circle: function (x, y, fill) {
this.ctx.beginPath();
this.ctx.arc(x, y, 20, 0, Math.PI * 2, false);
if (fill) {
this.ctx.fill();
} else {
this.ctx.stroke();
}
},
draw: function() {
Ball.ctx.clearRect(0, 0, 400, 400);
if (Ball.keyLeft) Ball.positionX -= 5;
else if (Ball.keyRight) Ball.positionX += 5;
if (Ball.keyUp) Ball.positionY -= 5;
else if (Ball.keyDown) Ball.positionY += 5;
Ball.circle(Ball.positionX, Ball.positionY, true);
}
}
Ball.init();
$('body').keydown(function (e) {
var key = e.keyCode;
if (key == 37) {
Ball.keyLeft = true;
} else if (key == 39) {
Ball.keyRight = true;
}
if (key == 38) {
Ball.keyUp = true;
} else if (key == 40) {
Ball.keyDown = true;
}
});
</script>
答案 0 :(得分:4)
Javascript(在浏览器中)是一种事件驱动的语言。大多数时候,没有任何东西被执行。当事件发生且脚本已为该特定类型的事件注册了侦听器时,该事件将被放入队列中。如果当前正在执行脚本的某些部分,它将不会被中断 - 相反,当它完成时,浏览器将从队列中提取下一个事件并开始为其执行注册的处理程序。
在您的代码中,您正在注册两种事件:计时器事件(隐式地,使用setInterval
)和keydown
事件(显式地,使用jQuery,它使用addEventListener
)。触发计时器事件时,将执行Ball.draw
方法。如果keydown
事件在运行时到达,它将在队列中等待Ball.draw
完成。然后将它分派给您指定的处理函数。反之亦然:如果keydown
处理程序正在进行,10毫秒通过,并且发生计时器事件,则计时器事件必须等到keydown
处理程序完成。这就是为什么Javascript计时器本质上不精确的一个原因。
简短版:您的keydown
处理程序可以在Ball.draw
的执行之间执行。在Ball.draw
下次调用时,它对两个函数使用的变量所做的任何更改都将可见。
答案 1 :(得分:2)
setInterval方法调度事件以供将来执行,但在时间结束并且调用该方法之前不会阻塞。 JS将在方法调用期间阻塞,并在完成时停止阻塞。
编写此代码的方式,每隔10ms将调用draw方法(这比浏览器甚至可以渲染的速度快60 fps或〜每16ms)。如果自上次调用后发生了keydown事件,则draw方法将获取新的布尔值/设置并采取适当的操作。
有关时间的更多信息,请参阅notes section on MDN
答案 2 :(得分:1)
JavaScript是单线程的,所以即使你有一个多处理器设备,javascript代码也会在该单个线程上执行。
setInterval
以“异步”方式运行,但是...... 异步并不意味着代码在单独的线程或处理器上运行。这意味着您的同步代码和异步代码在队列中发出时间片。并且只有一个且只有一个线程正在为该队列中的所有切片提供服务。
您的setInterval
将尝试执行每个#ms但它将被其他操作阻止,并且只会在唯一线程可用时执行。因此setInterval
无法保证以指定的时间间隔执行。
触发键(或鼠标)事件时,该事件将被放入队列,但不会调用键事件处理程序。该关键事件处理程序将在其原始事件发生在队列中时运行。