让我们来看看下面的代码:
console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);
一份请求进来后,JS引擎开始逐步执行上面的代码。前两个调用都是同步调用。但是,当到达setTimeout方法时,它变成了异步执行。但是JS立即从中返回并继续执行,这称为非阻塞或异步执行。然后它继续在其他等待操作工作。其执行结果如下:
"a c d b"
因此,基本上第二个setTimeout先完成,并且它的回调函数比第一个更早地被执行,这很有意义。
我们正在谈论单线程应用程序。JS引擎保持执行此操作,除非完成第一个请求,否则它不会转向第二个请求。但是好处是它不会等待像setTimeout这样的阻塞操作解决,因此它将更快,因为它接受新的传入请求。
但我的问题围绕以下项目产生:
#1: 如果我们谈论单线程应用程序,那么在JS引擎接受更多请求并执行它们时,什么机制处理setTimeouts?单线程如何继续处理其他请求?当其他请求不断到来并得到执行时,setTimeouts如何工作。
#2: 如果这些setTimeout函数在更多请求进来并被执行的同时在后台执行,那么是什么执行异步操作的?我们所说的EventLoop是什么?
#3: 但是整个方法不应该放在EventLoop中,以便整个过程得到执行并调用回调方法吗?当谈论回调函数时,这就是我的理解:
function downloadFile(filePath, callback)
{
blah.downloadFile(filePath);
callback();
}
但在这种情况下,JS引擎如何知道它是异步函数,以便将回调放入EventLoop
中?也许类似于C#中的async
关键字或某种属性,指示JS引擎将采用的方法是异步方法,并应相应处理。
#4:但一篇article与我猜测的工作方式完全相反:
事件循环是回调函数的队列。当异步函数执行时,回调函数被推入队列中。JavaScript引擎直到异步函数后的代码执行后才开始处理事件循环。
#5:还有这张图片可能有所帮助,但图像中的第一个解释与问题4中提到的完全相同: