我正在考虑,这是我想到的:
假设我们有这样的代码:
console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);
一个请求进入,并且JS引擎逐步开始执行上述代码。前两个呼叫是同步呼叫。但是当涉及到setTimeout
方法时,它将成为异步执行。但是JS立即从中返回并继续执行,这称为Non- Blocking
或Async
。并且它继续在其他等等上工作。
执行结果如下:
交流数据库
因此,基本上第二个setTimeout
首先完成,其回调函数比第一个早执行,这是有道理的。
我们在这里谈论单线程应用程序。JS
Engine会继续执行此操作,除非它完成第一个请求,否则它将不会转到第二个请求。但是,好处是它不会等待诸如setTimeout
解析之类的阻塞操作,因此它会更快,因为它接受新的传入请求。
但是我的问题围绕以下几个方面提出:
#1:
如果我们在谈论单线程应用程序,那么setTimeouts
当JS引擎接受更多请求并执行它们时,什么机制会处理?单线程如何继续处理其他请求?setTimeout
在其他请求不断进入并执行的同时,什么起作用了。
#2:
如果这些setTimeout
函数在更多请求传入并正在执行时在后台执行,那么在后台执行异步执行的是什么?我们所说的这个东西叫EventLoop
什么?
#3: 但是不应该将整个方法都放入EventLoop
以便执行整个过程并调用回调方法吗?这是我在谈论回调函数时所了解的:
function downloadFile(filePath, callback)
{
blah.downloadFile(filePath);
callback();
}
但是在这种情况下,JS引擎如何知道它是否是一个异步函数,以便可以将回调函数放在EventLoop? Perhaps something like the
C#中的async`关键字中或某种表明JS引擎将采用的方法的属性是异步方法并应予以相应对待。
#4: 但是一篇文章说与我猜测事情可能如何运作完全相反:
事件循环是回调函数的队列。当执行异步函数时,回调函数将被推入队列。在执行异步函数后的代码之前,JavaScript引擎不会开始处理事件循环。
#5: 这里有这张图片可能会有所帮助,但是图片中的第一个解释是说问题4中提到的完全相同的内容:
因此,我的问题是要对上述项目进行一些澄清?
1:如果我们谈论的是单线程应用程序,那么当JS引擎接受更多请求并执行它们时,什么处理setTimeouts?那不是单线程将继续处理其他请求吗?然后谁将继续处理setTimeout,而其他请求继续出现并被执行。
节点进程中只有1个线程可以实际执行程序的JavaScript。但是,在节点本身内部,实际上有多个线程处理事件循环机制的操作,其中包括IO线程池以及其他几个线程。关键是这些线程的数量与在每个连接线程的并发模型中处理的并发连接的数量不同。
现在关于“执行setTimeouts”,当您调用时setTimeout
,所有节点所做的基本上就是更新将来一次执行的函数的数据结构。它基本上有一堆需要做的事情,并且事件循环的每个“滴答声”都选择一个,将其从队列中删除,然后运行它。
需要了解的关键一点是,在大多数繁重的工作中,节点都依赖于操作系统。因此,传入的网络请求实际上是由OS本身跟踪的,当节点准备好处理一个网络请求时,它仅使用系统调用向OS询问网络请求,其中包含准备好处理的数据。IO的“工作”节点所做的大部分工作就是“嘿,操作系统,已准备好读取数据的网络连接?”
或“嘿,操作系统,我所有未完成的文件系统调用都已准备好数据?”。根据其内部算法和事件循环引擎设计,节点将选择一个“ tick”
JavaScript来执行,运行它,然后再次重复该过程。这就是事件循环的含义。基本上,节点始终在确定“接下来我应该运行什么JavaScript?”,然后运行它。setTimeout
或process.nextTick
。
2:如果这些setTimeout将在更多请求传入和执行期间在后台执行,那么在后台执行异步执行的事情就是我们在谈论EventLoop吗?
没有JavaScript在后台执行。程序中的所有JavaScript一次都运行在前面和中间。幕后发生的事情是OS处理IO,而节点等待IO准备就绪,然后节点管理等待执行的javascript队列。
3:JS引擎如何知道它是否是异步函数,以便可以将其放入EventLoop中?
节点核心中有一组固定的函数是异步的,因为它们进行系统调用,而节点知道这些是什么,因为它们必须调用OS或C
++。基本上所有网络和文件系统IO以及子进程的交互都是异步的,JavaScript可以使节点异步运行某些东西的唯一方法是调用节点核心库提供的异步功能之一。即使您使用定义其自己的API的npm包,也要生成事件循环,最终,该npm包的代码将调用节点核心的异步功能之一,并且在该时刻,节点知道滴答已完成并且可以启动事件再次循环算法。
4事件循环是回调函数的队列。当执行异步函数时,回调函数将被推入队列。在执行异步函数后的代码之前,JavaScript引擎不会开始处理事件循环。
是的,这是真的,但这是误导。关键是正常模式是:
//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
因此,是的,您可以通过仅在同一滴答声中同步计数所有内存中的斐波那契数来完全阻止事件循环,是的,这将完全冻结您的程序。这是合作并发。JavaScript的每一个滴答声都必须在合理的时间内产生事件循环,否则整个架构就会失败。
本文向大家介绍你对事件循环有了解吗?说说看!相关面试题,主要包含被问及你对事件循环有了解吗?说说看!时的应答技巧和注意事项,需要的朋友参考一下 学习了一波,出了一波笔记 https://www.yinzhuoei.com/index.php/archives/112/
本文向大家介绍理解JS事件循环,包括了理解JS事件循环的使用技巧和注意事项,需要的朋友参考一下 伴随着JavaScript这种web浏览器脚本语言的普及,对它的事件驱动交互模型,以及它与Ruby、Python和Java中常见的请求-响应模型的区别有一个基本了解,对您是有益的。在这篇文章中,我将解释一些JavaScript并发模型的核心概念,包括其事件循环和消息队列,希望能够提升你对一种语言的理解,
本文向大家介绍详解JavaScript事件循环机制,包括了详解JavaScript事件循环机制的使用技巧和注意事项,需要的朋友参考一下 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心。可看HTML规范中的这段话: To coordinate events, user interaction
事件是应用程序与自身各个功能模块以及与操作系统进行通讯的手段,也是实现事件驱动编程模型的基础,应用程序如果要响应这些事件,通常是创建一个事件队列来集中存放它们,从事件队列取出事件并调用对应处理器就是一次事件响应,而往复执行这个操作的过程就是事件循环。 驱动接口 LCUI 对事件循环的操作有处理事件、绑定事件和解绑事件,驱动模块的职责就是基于操作系统接口向 LCUI 提供实现了这些操作的接口。首先我
问题内容: nodejs体系结构内部是否存在两个事件循环? libev / libuv v8 javascript事件循环 在I / O请求上,节点是否将请求排队到libeio,而libeio又通过使用libev的事件通知数据的可用性,最后这些事件由v8事件循环使用回调来处理? 基本上,libev和libeio如何集成到nodejs架构中? 是否有任何文档可以清楚地了解nodejs内部体系结构?
主要内容:事件驱动程序,实例,Node 应用程序是如何工作的?Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。 Node.js 几乎每一个 API 都是支持回调函数的。 Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。 Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发