如何在javascript中进行时间切片?

时间:2012-09-08 16:22:34

标签: javascript ecma262

或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在同步代码块结束时是停止执行还是在任何随机点切断一个块以允许异步运行另一个块?

2 个答案:

答案 0 :(得分:6)

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

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

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

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

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

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

作为一个例子,我们假设我们有一个需要1秒钟加载的图像和一个需要5秒钟才能运行的CPU密集型功能。然后我们有这个代码:

my_cpu_heavy_function

当我们运行此代码时,即使图像只需要1秒钟在浏览器内部加载,onload处理程序也不会被调用,直到var img = new Image(); img.onload = function() { alert("image is loaded now"); } img.src = "xxx.jpg"; 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?

答案 1 :(得分:5)

  

如果我做A或B

会有什么不同吗?

是的,它会有所作为。

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

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

那么将会发生的事情是动画将开始并执行初始化,但my_cpu_heavy_function将立即启动,并阻止动画的其余部分直到完成。