7

或 ecmascript 但我想知道它实际上是如何发生的更多地取决于确切的实施。

javascript 在技术上是单线程的。

但如果我做类似的事情

$myDIv.animate({
    height:"100px"
});

如果我这样做有什么不同吗

一种。

$myDIv.animate({
    height:"100px"
}, null, my_cpu_heavy_function);

或 B。

$myDIv.animate({
    height:"100px"
});
my_cpu_heavy_function();

因为在第二个中,动画将与 cpu 繁重的功能争夺处理时间,因此动画的外观会受到影响,对吗?

那么 Javascript 是在同步代码块的末尾停止执行,还是在任何随机点切断一个块以允许处理另一个异步运行的块?

4

2 回答 2

6

javascript中没有时间切片。Javascript 是单线程的(除了我们不在这里讨论的网络工作者)。一个 javascript 执行线程一直运行,直到完成。

在您的第一个代码示例中,动画完成了它的工作,当它完全完成时,它调用您的my_cpu_heavy_function.

在您的第二个代码示例中,动画会自行初始化并为其第一个动画步骤设置一个计时器。然后它返回并进入下一行代码。动画才刚刚开始(并在未来设置了一个很短的时间来做更多的工作)——它还没有完成。然后,你的my_cpu_heavy_function运行它会占用整个 javascript 执行,直到它完成。动画在运行时根本不my_cpu_heavy_function运行。当它完成时,动画设置的定时器事件将触发并且动画将开始运行。

动画可能“看起来”像时间切片,但实际上并非如此。jQuery 动画在动画中移动一步,然后为将来的一小段时间设置一个计时器,然后返回系统。当那个计时器事件触发时,jQuery 会在动画中执行下一步,依此类推。当定时器事件触发时,它会将定时器事件放入 javascript 事件队列。如果当前没有运行 javascript,则立即启动计时器回调。如果 javascript 当前正在运行,则计时器事件仅位于事件队列中,直到当前 javascript 线程完成。当该线程完成时,javascript 会在事件队列中查看是否有任何事件在等待。如果有,则调用事件回调。

因此,对于不同的 javascript 片段确实没有时间切片。两个想要运行的代码并没有给定一些 CPU 周期,就像本机代码中的真实线程会发生的那样。在 javascript 中,一段代码一直运行到完成,然后可以开始下一个事件。在基于 javascript 的动画之类的东西中,时间切片可以通过做少量的工作来模拟,然后为将来的某个时间设置一个计时器并返回到系统。一旦你完成执行,其他一些 javascript 就可以运行,但它也会一直运行直到它完成。如果所有的javascript只做少量的工作,然后为他们的下一个工作设置一个计时器,那么它们都可以合作,看起来就像有时间切片,但它只是因为它们之间的合作才起作用。my_cpu_heavy_function出现并占用 CPU 一段时间,在此期间没有其他人运行。my_cpu_heavy_function动画将在运行时停止。

浏览器中的某些操作是由浏览器中的本机代码执行的(例如ajax调用、图像加载等)。这些异步任务可以在 javascript 运行时在后台继续执行,但它们不会通知 javascript,直到当前的 javascript 执行线程完成并且可以启动具有通知回调的新线程。

例如,假设我们有一个需要 1 秒加载的图像和一个需要 5 秒运行的 CPU 密集型函数。然后我们有这个代码:

var img = new Image();
img.onload = function() {
    alert("image is loaded now");
}
img.src = "xxx.jpg";
longFunctionThatTakesFiveSecondsToRun();

当我们运行这段代码时,即使图像只需要 1 秒在浏览器内部加载,onload 处理程序也不会被调用,直到longFunctionThatTakesFiveSecondsToRun()5 秒后运行完成。它必须等到当前执行线程完成后才能处理 onload 事件。

如果您想了解有关 javascript 事件队列和异步操作的更多信息,请参阅以下相关答案:

JavaScript 如何在后台处理 AJAX 响应?

JavaScript 事件处理的竞争条件?

JS 事件处理程序可以中断另一个处理程序的执行吗?

我需要关注异步 Javascript 的竞争条件吗?

于 2012-09-08T16:38:52.247 回答
5

如果我做A或B有什么不同吗

是的,它会有所作为。

第二个版本并没有为处理时间而争吵。假设它是同步的,它更像是my_cpu_heavy_function一旦开始就会占用所有处理时间。

换句话说,一旦同步代码开始,它不会在完成之前结束,而不管任何可能被调度运行的定时异步代码。异步代码将始终被迫等待同步代码完成。

所以将会发生的情况是动画将开始,并执行其初始化,但随后my_cpu_heavy_function将立即开始,并阻止动画的其余部分,直到它完成。

于 2012-09-08T16:27:51.033 回答