如何解决什么会进入Javascript的事件循环?
我知道javascript是单线程的,这意味着javascript运行时(浏览器或Node等)会将花费时间的任务发送到事件循环,以便执行平稳运行而不会阻塞它所拥有的线程。但是我对运行时如何决定事件循环的处理方式感到困惑。 (进入事件循环必须执行一些代码块操作)。这可能是由于我缺乏理解,但是无论如何,我将通过一个例子来阐述我的问题。
function first() {
console.log('first');
}
function second() {
console.log('second');
}
first()
let i=0;
while(i<1000000000000){
i++
}
second();
在此senario控制台中,先打印“ first”,然后花费大量时间(可能卡住),再打印“ second”。这样一来,虽然代码块不会进入事件循环。
function first() {
console.log('first');
}
function second() {
console.log('second');
}
first()
setTimeout(()=>{},500000);
second();
在这种情况下不是这样,首先,它打印“ first”,然后将setTimeout加载到堆栈,但是这需要时间,因此将其移到事件循环中,继续执行线程,然后打印“ second”。 500000 ms之后,setTime将返回到调用堆栈,从而返回线程。
所以我想知道为什么“ while块”没有进入事件循环,而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();
第一个:功能第一个已添加到JavaScript调用堆栈中,它输出console.log,然后,第一个功能是从调用堆栈中删除。
第二个::浏览器在其Web API引擎中添加了setTimeout,并为其创建了一个计时器(500秒)。
第3次::功能 second 已添加到JavaScript调用堆栈中,它输出console.log,然后从调用堆栈中删除。
第4个::上一个计时器结束时,浏览器将setTimeout的回调函数(不是setTimeout本身)放入事件循环任务队列中,可以开始运行了
第5个::事件循环查看调用堆栈,并等待直到调用堆栈为空。好的,它是空的,因此事件循环将任务放入调用堆栈并执行。
在setTimeout计时器为零的情况下也会发生同样的情况。
setTimeout(()=> {},0);
如果调用堆栈有很多任务,则setTimeout回调函数可以比其计时器(第二个参数)等待更多的时间
请注意,setTimeout并不是时间的保证,而是最短的时间。
这是关于事件循环的great lecture。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。