Javascript中的事件循环是什么?

Javascript中的事件循环是什么?,javascript,callback,v8,callstack,event-loop,Javascript,Callback,V8,Callstack,Event Loop,我知道javascript是单线程的,这意味着javascript运行时(浏览器或节点等)将向事件循环发送耗时的任务,以便执行顺利运行,而不会阻塞它所拥有的线程。但对于运行时如何决定哪些内容进入事件循环,我有点困惑。(一些代码块必须做什么才能进入事件循环)。这可能是因为我缺乏理解,但无论如何,我会用一个例子来阐述我的问题 function first() { console.log('first'); } function second() { console.log('second');

我知道javascript是单线程的,这意味着javascript运行时(浏览器或节点等)将向事件循环发送耗时的任务,以便执行顺利运行,而不会阻塞它所拥有的线程。但对于运行时如何决定哪些内容进入事件循环,我有点困惑。(一些代码块必须做什么才能进入事件循环)。这可能是因为我缺乏理解,但无论如何,我会用一个例子来阐述我的问题

function first() {
 console.log('first');
}

function second() {
 console.log('second');
}

first()
let i=0;
while(i<1000000000000){
 i++
}
second();
这里不是这样,首先,它打印'First',然后将setTimeout加载到堆栈中,但这需要时间,所以将其移动到事件循环中,继续线程,然后打印'second'。500000毫秒后,它将返回调用堆栈,从而返回线程


所以我想知道为什么“while block”不进入事件循环,而setTimeout进入事件循环。是因为setTimeout是一个异步调用吗但是运行时怎么知道它是异步的呢?

好的,首先:JavaScript引擎对
setTimeout
函数一无所知。在高层,JavaScript引擎只有一个用于内存管理的调用堆栈和堆。
setTimeout
不是JavaScript引擎的一部分,它与浏览器的Web API一起提供。setTimeout永远不会进入调用堆栈,它的回调函数会在适当的时间进入

调用
setTimeout
时,浏览器会为其创建一个计时器并将其放入内存中,当计时器结束时,浏览器会获取其回调函数并将其放入事件循环任务队列中,而不是JavaScript引擎调用堆栈中。因此,事件循环实际做的是不断观察JavaScrip调用堆栈,当调用堆栈为空时,它获取其任务队列的第一个任务并将其放入调用堆栈中

假设您有以下代码:

function first() {
 console.log('first');
}

function second() {
 console.log('second');
}

first()
setTimeout(()=>{},500000);
second();
1st:函数first被添加到JavaScript调用堆栈中,它输出一个console.log,然后从调用堆栈中删除first函数

2nd:浏览器在其web API引擎中添加setTimeout,并为其创建计时器(500秒)

3rd:函数second被添加到JavaScript调用堆栈中,它输出一个console.log,然后从调用堆栈中删除

4th:当上一个计时器结束时,浏览器将setTimeout的回调函数(而不是setTimeout本身)放入事件循环任务队列中,即可运行

5th:事件循环查看调用堆栈并等待,直到调用堆栈为空。好的,它是空的,因此事件循环将任务放入调用堆栈并执行

设置超时计时器为零的情况下也会发生同样的情况

setTimeout(()=>{},0)

如果调用堆栈有很多任务,setTimeout回调函数可以比其计时器等待更长的时间(第二个参数)

请注意,setTimeout不是时间的保证,而是最短时间的保证


这是一个关于事件循环的示例。

setTimeout(500000)“运行时将向事件循环发送耗时任务”-否。有些任务可以在后台“执行”,如等待计时器或网络响应,只有完成这些操作后,进入事件队列的任务才是执行为事件注册的回调javascript代码。运行时知道您调用了setTimeout。无论你们作为参数传递什么,都将以异步方式执行。谢谢,伙计们,现在更清楚了!!啊,现在我明白了。我对这件事感到很困惑。这是一个完美的答案。谢谢不客气,兄弟。我强烈建议您查看链接中的讲座。“因此,事件循环实际做的是不断观察JavaScrip调用堆栈,当调用堆栈为空时,它会抓住任务队列中的第一个任务并将其放入调用堆栈中。”JS没有那么重要,事件循环还有许多其他任务要处理,而不是JS执行。还有一个优先级系统,所以他们会执行一个任务队列中的第一个任务,而不是第一个任务队列。你说得对@kaido,我想让这个概念保持简单。但实际上,有任务、微任务和渲染器任务队列,每个队列都有自己的行为。此外,在Chrome、Safari、Firefox和Edge中,事件循环以不同的方式处理requestAnimationFrame。在这个领域有很多东西需要探索。
function first() {
 console.log('first');
}

function second() {
 console.log('second');
}

first()
setTimeout(()=>{},500000);
second();