Node.js Event-loop事件循环

简介: node.js事件循环Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。

node.js事件循环


Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高。
Node.js 的每一个 API 都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发。
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.

事件驱动程序


想要理解Event Loop,就要从程序的运行模式讲起。运行以后的程序叫做"进程"(process),一般情况下,一个进程一次只能执行一个任务。
如果有很多任务需要执行,不外乎三种解决方法。
(1)排队:因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。
(2)新建进程:使用fork命令,为每个任务新建一个进程。
(3)新建线程:因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务。(进程和线程的详细解释,请看这里。)

以JavaScript语言为例,它是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现"假死",因为JavaScript停不下来,也就无法响应用户的行为。
你也许会问,JavaScript为什么是单线程,难道不能实现为多线程吗?
这跟历史有关系。JavaScript从诞生起就是单线程。原因大概是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API可以实现多线程,但是JavaScript本身始终是单线程的。)
如果某个任务很耗时,比如涉及很多I/O(输入/输出)操作,那么线程的运行大概是下面的样子。


img_af5f5433a24b26a32fa6a3e879ec825e.png
单线程运行任务示意图

上图的绿色部分是程序的运行时间,红色部分是等待时间。可以看到,由于I/O操作很慢,所以这个线程的大部分运行时间都在空等I/O操作的返回结果。这种运行方式称为"同步模式"(synchronous I/O)或"堵塞模式"(blocking I/O)。
如果采用多线程,同时运行多个任务,那很可能就是下面这样。


img_e1beb34a9a45a6f82dc5e471075b7716.png
多线程运行任务示意图

上图表明,多线程不仅占用多倍的系统资源,也闲置多倍的资源,这显然不合理。
Event Loop就是为了解决这个问题而提出的。Wikipedia这样定义:
Event Loop是一个程序结构,用于等待和发送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)

简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。

img_4134383526723090201bbc4116cf2cac.png
事件循环示意图

上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。
可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。
这正是JavaScript语言的运行方式。单线程模型虽然对JavaScript构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果部署得好,JavaScript程序是不会出现堵塞的,这就是为什么node.js平台可以用很少的资源,应付大流量访问的原因。

代码体现


创建一个main.js文件

 //引入events模块
 var events = require('events');
 //创建eventEmitter对象 内部类对象
 var eventEmitter = new events.EventEmitter();
 //创建事件处理程序
 var connectHandler = function connected() {
      console.log('连接成功');
     //触发data_received事件
      evenEmitter.emit('data_received');
 }
 //创建 名为connection 事件,并将事件处理程序(回调函数)绑定到事件上
 eventEmitter.on('connection',connectHandler);
 //创建名为data_reveived事件,并将匿名处理函数(回调函数)绑定到事件上
 eventEmitter.on('data_received',function() {
       console.log('数据接收成功');
 })
 //触发connection 事件
 eventEmitter.emit('connection');

 console.log("程序执行完毕");

接下来让我们执行以上代码:

$ node main.js
连接成功
数据接收成功
程序执行完毕

看了上面的程序如果还不懂的话,请看下面的这幅图,并结合最后一段话去理解:

img_de9a7314f89b21ecb7be488cfda2a161.jpe
node.js事件循环示意图

事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。
要点:
1.观察者相当于事件处理程序--被回调的函数。
2.事件就相当于我们认为的任务,比如程序执行期间需要等待I/O这就是一个事件。
3.我们可以把node.js的主线程想像成一个来者不拒的主人,这个人遇到什么事情都不拒绝,但是他处理事情也要找其他人(I/O)帮忙。
他有一个管家叫event loop线程,当事情来得时候,主人告诉管家这个事情,并让管家去找能够解决这个问题的人,然后继续接事情,当能够解决这个事情的人解决了事情,管家就把事情的结果告诉给主人,这里的回调函数可以想象成信鸽,主人将事情的结果放在信鸽身上(结果为参数,信鸽为回调函数载体),完成整个任务,这就说明node.js是异步执行的语言,非阻塞的语言,这也就是node.js性能高的原因。
4.node.js使用的是javascript语法,javascript语法是单线程的,当用户触发事件,事件会产生消息,消息会进入消息列表,在消息进入列表的同时,回调函数也进入列表,当消息出队列时,回调函数被调用。整个底层过程就是这样的

吴海星译


谢天谢地,实际情况不是这样的。当浏览器中有I/O操作时,该操作会在事件轮询的外面执
行(脚本执行的主顺序之外),然后当这个I/O操作完成时,它会发出一个“事件”,①会有一个函
数(通常称作“回调”)处理它,如图1-1所示。

img_32bac09170ae213bb39ad747b365955c.png

img_6dadba183a1fe152464db0a54bc87165.png
Paste_Image.png

博客搬家:大坤的个人博客
欢迎评论哦~

目录
相关文章
|
3月前
|
存储 JavaScript 前端开发
深入理解JavaScript中的事件循环(Event Loop):机制与实现
【10月更文挑战第12天】深入理解JavaScript中的事件循环(Event Loop):机制与实现
152 3
|
4月前
|
JavaScript 前端开发 API
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务
该文章详细讲解了队列数据结构在前端开发中的应用,并深入探讨了JavaScript的事件循环机制,区分了宏任务和微任务的执行顺序及其对前端性能的影响。
|
2月前
|
JavaScript 前端开发 API
深入理解Node.js事件循环及其在后端开发中的应用
本文旨在揭示Node.js的核心特性之一——事件循环,并探讨其对后端开发实践的深远影响。通过剖析事件循环的工作原理和关键组件,我们不仅能够更好地理解Node.js的非阻塞I/O模型,还能学会如何优化我们的后端应用以提高性能和响应能力。文章将结合实例分析事件循环在处理大量并发请求时的优势,以及如何避免常见的编程陷阱,从而为读者提供从理论到实践的全面指导。
|
2月前
|
JavaScript API 开发者
深入理解Node.js中的事件循环和异步编程
【10月更文挑战第41天】本文将通过浅显易懂的语言,带领读者探索Node.js背后的核心机制之一——事件循环。我们将从一个简单的故事开始,逐步揭示事件循环的奥秘,并通过实际代码示例展示如何在Node.js中利用这一特性进行高效的异步编程。无论你是初学者还是有经验的开发者,这篇文章都能让你对Node.js有更深刻的认识。
|
2月前
|
JavaScript 前端开发 开发者
JavaScript的事件循环
【10月更文挑战第27天】理解JavaScript的事件循环机制对于正确编写和理解JavaScript中的异步代码至关重要,它是JavaScript能够高效处理各种异步任务的关键所在。
47 1
|
3月前
|
前端开发 JavaScript
深入理解JavaScript中的事件循环(Event Loop):从原理到实践
【10月更文挑战第12天】 深入理解JavaScript中的事件循环(Event Loop):从原理到实践
53 1
|
3月前
|
Web App开发 JavaScript 前端开发
深入理解Node.js事件循环和异步编程模型
【10月更文挑战第9天】在JavaScript和Node.js中,事件循环和异步编程是实现高性能并发处理的基石。本文通过浅显易懂的语言和实际代码示例,带你一探究竟,了解事件循环的工作原理及其对Node.js异步编程的影响。从基础概念到实际应用,我们将一步步解锁Node.js背后的魔法,让你的后端开发技能更上一层楼!
|
3月前
|
设计模式 JavaScript API
Node.js 事件循环
10月更文挑战第3天
39 0
Node.js 事件循环
|
3月前
|
JavaScript 调度 数据库
深入浅出:Node.js中的异步编程与事件循环
【9月更文挑战第30天】在Node.js的世界里,理解异步编程和事件循环是掌握其核心的关键。本文将通过浅显易懂的语言和实际代码示例,带你探索Node.js如何处理并发请求,以及它是如何在幕后巧妙地调度任务的。我们将一起了解事件循环的各个阶段,并学会如何编写高效的异步代码,让你的应用程序运行得更加流畅。
75 10
|
3月前
|
JavaScript 前端开发 开发者
深入理解Node.js中的事件循环和异步编程
【9月更文挑战第31天】本文旨在揭示Node.js背后的强大动力——事件循环机制,并探讨其如何支撑起整个异步编程模型。我们将深入浅出地分析事件循环的工作原理,以及它如何影响应用程序的性能和稳定性。通过直观的例子,我们会展示如何在实际应用中利用事件循环来构建高性能、响应迅速的应用。此外,我们还会讨论如何避免常见的陷阱,确保代码既优雅又高效。无论你是Node.js的新手还是经验丰富的开发者,本篇文章都将为你提供宝贵的洞察和实用技巧。
74 6

热门文章

最新文章