Javascript如何单线程?

Tar*_*rik 40 javascript multithreading

我有一个关于Javascript的单线程性质的问题.

console.log("1");
setTimeout(function(){console.log("2");},3000);
console.log("3");
setTimeout(function(){console.log("4");},1000);
Run Code Online (Sandbox Code Playgroud)

这段代码的结果是1 3 4 2.如你所见,4之后2让我想知道在单线程环境中不应该2追求4?如果没有,那么为什么JS知道第二个setTimeout应该在第一个之前完成?难道不应该有两个同时工作的线程来完成两个setTimeouts才能通知EventLoop吗?

use*_*740 29

JavaScript(在浏览器中)不会同时运行2.

最多一个的的setTimeout回调可以同时执行-因为有一个 JavaScript执行上下文或"线程".

但是,运行的"下一个计划超时"始终运行..下一步."4"在"2"回调之前运行,因为它被安排更快地运行.超时被有效地安排来自同一时间(无操作被阻止),但"2"有一个更长的时间间隔.

底层实现可以使用线程1 - 但是同一全局上下文中的 JavaScript 不会并发运行并且保证所有回调之间的一致和原子行为.


1或者它可能不会; 这可以在没有实现中的任何线程的select/poll情况下处理.

2在相同的上下文中:即选项卡/窗口,WebWorker,主机浏览器控件.例如,当WebWorkers同时运行时,它们在不同的上下文中运行,并遵循相同的异步模型(例如,计时器使用的).

  • 我们都依赖于这种行为并观察它 - 但这记录在哪里? (9认同)

Sid*_*m H 15

Javascript使用名为Eventloop的东西进行异步调用.setTimeout被推送到EventLoop,因为它是一个回调.并且主线程继续执行.一旦主要完成,然后EventLoop将数据推送到主堆栈.例如:

console.log("1");
setTimeout(function(){console.log("2");},0);
console.log("3");
setTimeout(function(){console.log("4");},1000);
Run Code Online (Sandbox Code Playgroud)

当超时为0时,代码的输出将是,

1 3 2 4

因为它首先执行Main的调用,然后从Eventloop Concurrency模型和Event Loop中返回数据

  • 内容丰富且易于理解的+1 (4认同)

Bri*_*ity 11

Javascript按顺序执行每一行.

所以你告诉js:

  • 写1: js writes 1
  • 等待3秒然后写2: ok I'll wait 3 seconds...now what?
  • 写3: ok I'll write 3, by the way, the 3 seconds is not up.
  • 等待1秒然后写4: ok I'll wait 1 second...

然后js等待.99999秒...然后写4

然后再等一些,然后写2

  • "顺便说一句,3秒钟不起来"是误导.即使计时器已经到来,JavaScript也不可能在那里执行某些操作,正是因为JS是单线程的.JS线程可以是代码内代码,也可以是代码外代码; 虽然它是代码内的,但它不能执行任何其他操作.任何超时只发生在您的代码放弃JS引擎的命令时(通过退出最外层的函数). (3认同)

Nik*_*ahu 5

setTimeout的第二个参数占用最短的时间,之后将回调函数(第一个参数)推入事件循环,这只是回调函数的队列。使用此队列实际上开始执行。

一旦遇到第一个setTimeout,函数就会被推到外面的某个地方,并被告知要等待3秒钟,然后才能重新进入单线程世界。第二个超时功能也一样,但是只需要等待1秒钟。这个单线程世界的入口点是回调队列。JS Engine继续正常执行,就像完成settimeout执行一样。现在,一旦1秒钟过期,第二个超时功能将被推入队列并等待执行。如果在该时间点调用栈是清除的,则该函数将继续进行处理(假设它是队列的第一个成员),并显示“ 4”。现在,如果此时还没有经过3秒,则第一次超时的功能仍在外面某个地方等待。3秒过后,回调函数将进入队列,并且由于调用堆栈已清除,

现在,浏览器可以从操作系统访问多个线程(尽管仅为JS执行提供一个线程环境)。这些setTimeouts由后台的另一个线程处理。

飞利浦·罗伯特(Philip Robert)播放了一段视频,详细介绍了导致单线程javascript的“异步性”的队列和事件循环的概念。

https://www.youtube.com/watch?v=8aGhZQkoFbQ