当前位置: 首页 > 后端技术 > Node.js

理解node.js中的EventLoop

时间:2023-04-03 21:04:36 Node.js

node中的“事件循环”是node处理高并发能力的核心。也正是因为如此,node虽然本质上是单线程,但却允许大量的操作在后台运行。本文将详细介绍事件循环的工作原理。事件驱动编程要理解事件循环,首先要理解事件驱动编程的概念。自1960年代以来,事件驱动编程的概念就广为人知。它在当今的UI编程中被广泛使用。由于JavaScript的主要功能是操作DOM,因此使用基于事件的API是很自然的。简单来说,事件驱动编程就是指程序的控制流是基于事件或事件状态的变化。一个常见的实现是定义一个监听事件的核心机制,当被监听的事件发生或状态发生变化时,回调注册在该事件上的回调方法。事实上,这就是事件循环背后的基本原理。如果你熟悉前端js开发,你可能会想到.onXxx()方法,比如element.onclick(),这些方法就是监听用户对DOM元素的操作。这种模式适用于单个元素可能触发多个不同事件的情况。Node中的EventEmitter就是采用这种模式,它存在于Node的Server、Socket、http等多个模块中。当我们需要从一个对象发送多个状态更改时,这种模式非常有用。另一种常见的模式是成功状态的回调和失败状态的回调。目前主要有两种实现方式。一种是error-first回调方式:即当发生错误时,将错误信息作为第一个参数传递给回调方法。另一种方式是ES6中的Promises。Node中的fs模块主要使用了错误回调优先级的方法。从技术上讲,它可以为某些调用发送额外的事件,例如fs.readFile(),但API旨在仅在用户指定的操作成功或失败时通知用户。之所以这样设计API,只是出于架构上的考虑,而非技术上的限制。一个常见的误解是认为事件的发送者是异步的,但事实并非如此。下面的例子可以很好地说明它:.emit('fire')console.log('after')}};varme=newMyEmitter();me.on('fire',function(){console.log('emitfired');});me.doStuff();//输出结果为//before//emitfired//afterEventEmitter通常用于发送异步操作的完成,因此经常被误解为异步操作,而实际上它本身是同步的。emit函数可能会被异步调用,但需要注意的是,所有的回调函数都会按照注册的顺序同步执行。EventLoop机制概述Node本身依赖于多个库,libuv是其中之一。libuv负责处理队列和进程中的异步事件。Node也会尽可能利用操作系统中的功能。因此,诸如写请求、维护连接等都交给操作系统来处理。会介入。你可能知道node中有线程池,那么你会有一个疑问:Node既然把那些耗时的操作都交给了操作系统,为什么还需要线程池呢?这是因为操作系统内核并不支持所有操作都采用异步操作。在这种情况下,节点需要锁定那些正在执行不支持异步操作的内核的线程,并使用其他线程进行事件循环,以免阻塞整个进程。下图是整个机制的简化图:还有两个重要的点很难在图中表现出来:未完待续。....