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 响应? https://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background/7575649#7575649
JavaScript 事件处理的竞争条件? https://stackoverflow.com/questions/8611145/race-conditions-with-javascript-event-handling/8611469#8611469
JS 事件处理程序可以中断另一个处理程序的执行吗? https://stackoverflow.com/questions/8016001/can-js-event-handlers-interrupt-execution-of-another-handler/8016185#8016185
我是否需要关心异步 Javascript 的竞争条件? https://stackoverflow.com/questions/7238586/do-i-need-to-be-concerned-with-race-conditions-with-asynchronous-javascript/7238663#7238663