javascript - javascript 中的时间切片是如何发生的?

标签 javascript ecma262

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

javascript 在技术上是单线程的。

但是如果我做类似的事情

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

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

A.

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

或 B.

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

因为在第二个动画中,动画会与 cpu 繁重的函数争夺处理时间,所以动画的外观会受到影响,对吧?

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

最佳答案

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

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

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

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

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

浏览器中的某些操作是由浏览器中的 native 代码执行的(例如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 事件队列和异步操作的信息,请参阅这些相关答案:

How does JavaScript handle AJAX responses in the background?

Race conditions with JavaScript event handling?

Can JS event handlers interrupt execution of another handler?

Do I need to be concerned with race conditions with asynchronous Javascript?

关于javascript - javascript 中的时间切片是如何发生的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12332429/

相关文章:

javascript - 单击将每个 div 元素的 javascript 中的背景颜色重置为透明

javascript - 如何在拼接后为force.links()刷新eventFunction(d,index)中的 "index"?

javascript - 编写符合 ECMAScript5 的代码(第 2 部分)

javascript - ECMA-262 ReturnIfAbrupt

javascript - 如何找到浏览器中断一段文本的位置

javascript - 如何直接追加Json对象?

javascript - 样式组件内的动态最小最大值

javascript - ECMAScript 5 规范中可能存在拼写错误?

javascript - ECMA-262 严格模式下是否允许 '\0' 后跟字符串中的十进制数字?

javascript - 清楚 ECMAScript/JavaScript 中 "LexicalEnvironment"和 "VariableEnvironment"之间的区别