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