Javascript 了解事件循环
我正在考虑,这就是我想到的: 让我们看看下面的代码:Javascript 了解事件循环,javascript,multithreading,node.js,asynchronous,event-loop,Javascript,Multithreading,Node.js,Asynchronous,Event Loop,我正在考虑,这就是我想到的: 让我们看看下面的代码: console.clear(); 控制台日志(“a”); setTimeout(function(){console.log(“b”);},1000); 控制台日志(“c”); setTimeout(函数(){console.log(“d”);},0); 一个请求进入,JS引擎开始一步一步地执行上面的代码。前两个呼叫是同步呼叫。但是当涉及到setTimeout方法时,它就变成了异步执行。但是JS立即从它返回并继续执行,这被称为非阻塞或异步。
console.clear();
控制台日志(“a”);
setTimeout(function(){console.log(“b”);},1000);
控制台日志(“c”);
setTimeout(函数(){console.log(“d”);},0);
一个请求进入,JS引擎开始一步一步地执行上面的代码。前两个呼叫是同步呼叫。但是当涉及到setTimeout
方法时,它就变成了异步执行。但是JS立即从它返回并继续执行,这被称为非阻塞
或异步
。并继续在其他方面开展工作
此执行的结果如下所示:
a、c、d、b
因此,基本上第二个setTimeout
首先完成,它的回调函数比第一个更早执行,这是有意义的
这里我们讨论的是单线程应用程序。JS引擎一直在执行这个请求,除非它完成第一个请求,否则它不会转到第二个请求。但好的是,它不会等待诸如setTimeout
之类的阻塞操作来解决,因此它会更快,因为它接受新的传入请求
但我的问题围绕以下几点:
#1:如果我们谈论的是单线程应用程序,那么当JS引擎接受更多请求并执行它们时,什么机制处理设置超时?单线程如何继续处理其他请求?当其他请求不断进入并得到执行时,在setTimeout
上工作的内容
#2:如果这些设置超时
函数在幕后执行,而更多请求进入并被执行,那么在幕后执行异步执行的是什么?我们谈论的这个叫做EventLoop
的东西是什么
#3:但是整个方法不应该放在EventLoop
中,以便执行整个过程并调用回调方法吗?这就是我在谈论回调函数时的理解:
函数下载文件(文件路径,回调)
{
下载文件(文件路径);
回调();
}
但是在本例中,JS引擎如何知道它是否是一个异步函数,以便将回调放入EventLoop
?也许像C#中的async
关键字之类的东西,或者某种表示JS引擎将采用的方法是一种异步方法的属性,应该进行相应的处理
#4:但安的说法与我所猜测的情况完全相反:
事件循环是回调函数的队列。当一个异步
函数执行时,回调函数被推入队列。这个
JavaScript引擎直到
执行异步函数后的代码
#5:这里有一张图片可能会有帮助,但图片中的第一个解释与问题4中提到的完全相同:
因此,我的问题是对上面列出的项目进行一些澄清?不要认为主机进程是单线程的,它们不是。单线程是主机进程中执行javascript代码的部分
除了,但这些使情况复杂化了
因此,所有js代码都在同一个线程中运行,并且不可能让js代码的两个不同部分同时运行(因此,不需要管理并发性)
正在执行的js代码是主机进程从事件循环中获取的最后一个代码。
在您的代码中,您基本上可以做两件事:运行同步指令,以及在将来发生某些事件时安排要执行的函数
下面是我对示例代码的心理表达(注意:只是,我不知道浏览器实现的细节!):
console.clear(); //exec sync
console.log("a"); //exec sync
setTimeout( //schedule inAWhile to be executed at now +1 s
function inAWhile(){
console.log("b");
},1000);
console.log("c"); //exec sync
setTimeout(
function justNow(){ //schedule justNow to be executed just now
console.log("d");
},0);
当代码运行时,主机进程中的另一个线程跟踪正在发生的所有系统事件(单击UI、读取文件、接收网络数据包等)
代码完成后,它将从事件循环中删除,主机进程将返回检查它,以查看是否还有更多代码要运行。事件循环包含两个以上的事件处理程序:一个立即执行(justNow函数),另一个在一秒钟内执行(inAWhile函数)
主机进程现在尝试匹配所有发生的事件,以查看是否有为它们注册的处理程序。
它发现justNow等待的事件已经发生,因此它开始运行代码。当justNow函数退出时,它会再次检查事件循环,搜索事件的处理程序。假设1s已过,它将运行inAWhile函数,依此类推
1:如果我们谈论的是一个单线程应用程序,那么当JS引擎接受更多请求并执行它们时,是什么处理设置超时?单线程不是会继续处理其他请求吗?那么,当其他请求不断出现并被执行时,谁将继续处理setTimeout呢
节点进程中只有一个线程将实际执行程序的JavaScript。然而,在节点本身中,实际上有几个线程处理事件循环机制的操作,这包括一个IO线程池和一些其他线程。关键是这些线程的数量与正在处理的并发连接的数量不一致,就像在每个连接一个线程并发模型中那样
关于“执行setTimeout”,当您调用setTimeout
时,节点所做的基本上就是更新将来某个时间要执行的函数的数据结构。它基本上有一大堆需要处理的事情,它选择的事件循环的每一个“勾号”都会删除i
//Let's say this code is running in tick 1
fs.readFile("/home/barney/colors.txt", function (error, data) {
//The code inside this callback function will absolutely NOT run in tick 1
//It will run in some tick >= 2
});
//This code will absolutely also run in tick 1
//HOWEVER, typically there's not much else to do here,
//so at some point soon after queueing up some async IO, this tick
//will have nothing useful to do so it will just end because the IO result
//is necessary before anything useful can be done
console.log("Start");
setTimeout(function cbT(){
console.log("Set time out");
},5000);
fetch("http://developerstips.com/").then(function cbF(){
console.log("Call back from developerstips");
});
// Millions of line code
// for example it will take 10000 millisecond to execute
console.log("End");
Start
End
Call back from developerstips
Set time out