Node.js 简介
约 2454 字大约 8 分钟
2025-03-15
一、什么是 Node.js
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,可以用来开发服务器端和网络应用。
- 非阻塞和事件驱动:Node.js 使用事件驱动和异步编程模型,能够处理大量并发请求,提高了应用程序的性能和吞吐量。
- 单线程:Node.js 使用单线程的事件循环机制,通过非阻塞 I/O 操作实现高并发处理。
- 轻量和高效:Node.js 运行时环境很轻量,启动快速,并且能够处理大量的并发连接。
- 跨平台:Node.js 可以在多个操作系统上运行,如 Windows、Mac 和 Linux。
- 丰富的模块生态系统:Node.js 拥有丰富的模块和包管理器 npm,可以方便地引用和管理各种功能模块。
- 可扩展性:Node.js 通过模块化的方式支持代码的重用和组件化开发,使得应用程序易于扩展和维护。
通过这些特点,Node.js 成为了开发高性能、高并发的网络应用和服务器端应用的首选。
主要用途和功能:
- 服务器端开发:Node.js 主要用于构建高性能、高并发的网络服务器,如 HTTP 服务器。2
- 实时应用:适合于开发实时交互应用,如聊天室、实时协作工具等。
- API 服务:常用于构建 RESTful API 服务器。
- 工具脚本:可以用来编写各种自动化脚本和命令行工具。 :::
性能优化
- 非阻塞 I/O:Node.js 是基于事件驱动和非阻塞 I/O 模型的,这意味着它可以同时处理大量的并发请求。通过使用回调函数和事件监听器,Node.js 可以在等待 I/O 操作完成时继续处理其他请求,从而提高性能和吞吐量。
- 异步编程:利用 JavaScript 的异步编程能力,可以通过使用异步 API、Promise 和 async/await 等技术,避免阻塞操作,提高代码的执行效率和响应能力。
- 多进程和集群:使用 Node.js 的集群模块(例如
cluster
模块)可以创建多个工作进程,以利用多核处理器和额外的计算资源,提高性能和负载均衡能力。 - 代码优化:优化 Node.js 应用程序的代码结构和算法,避免不必要的计算和复杂度高的操作,以提高代码的执行效率和响应速度。
- 使用高效的库和工具:选择高效的第三方库和工具,如 Express.js、Fastify、Redis 等,它们可以提供更好的性能和更高的吞吐量。
二、介绍几个重要概念
1、NPM 包管理器
npm(Node Package Manager)
是 Node.js
的标准包管理器,用于安装、发布、管理包依赖关系、以及运行某些脚本。类似于 java 中的 maven。
2、阻塞、非阻塞执行
阻塞 是当 Node.js
进程中的其他 JavaScript
的执行必须等到非 JavaScript
操作完成时。 发生这种情况是因为在发生 阻塞 操作时事件循环无法继续运行 JavaScript。一般来说,常见的阻塞场景,定时器(setInterval)
、计时器(setTimeout)
、异步请求(Ajax
、Promise
等)、I/O流
等。
非阻塞执行 指的是异步编程,Node.js
遇到阻塞性的代码时,将其交给操作系统,并立即执行下一条代码,等待操作系统执行完成后,操作系统会通知 Node.Js
,然后执行相应的回调函数
3、异步编程
在 Node.js 中,异步编程是核心的特性之一,是为了解决代码阻塞,提高运行效率的重要手段。Node.js 基于 事件循环
、回调函数
机制或 Promises
、async/await
等Javascript
,来实现非阻塞操作。
异步编程意味着在执行 I/O(输入/输出)操作时,程序不会阻塞当前线程去等待操作完成,而是继续执行其他任务,并在 I/O 操作完成时通过回调、事件监听器或 Promise 的 then 方法来处理结果。
4、回调
回调是一种异步编程的实现。我们通过给阻塞性的函数的传入一个函数作为参数,等该阻塞函数执行完毕时,我们触发该回调函数来实现对结果的处理,这个传入函数叫做回调函数
。他可以用来处理异步操作,避免代码阻塞,并且可以进行错误处理,同时也可以一定程度上实现逻辑走向的控制管理
// 回调函数
function callback () {
....
}
function doing(param, callback) {
Vue.ajax(param).then((res)=>{ // 假如 Vue.ajax是个异步接口请求
callback(res); // 执行回调函数callback,处理结果res
})
}
5、事件模块
事件模块和 Node.js
的事件循环是两回事。
事件模块是作为 Node.js 代码执行层面的一种用来监听事件、触发操作、模块间传递消息的机制。
而事件循环是 Node.js 框架用来实现并发和异步编程的的一种机制。
6、路由和中间件
路由 指的是将一个 URL 路径和一个资源的映射关系。路由可以指向服务器中一个确定的静态资源(如网页、css、js、图片等),也可以指向服务器开放的服务接口。
中间件 指的是在路由的请求和处理过程中,插入的一段处理逻辑,一般是一个函数或者一组函数,用来执行一些预处理或者后处理操作,比如修改请求报文,处理响应报文,错误处理,身份验证,日志记录。
7、缓存
模块缓存: 我们在引入模块时,
Node.js
会先去缓存中寻找该模块,如果找不到就去工程下寻找该模块,找到并引入以后,将依赖放入缓存中。内存缓存: 内存缓存指的是缓存业务数据,我们可以使用
Object
和map
来实现一个数据对象来临时存放着这些业务数据。数据缓存: 如果需要实现对数据库、外部 API、或者一些 耗时的网络、IO 操作 ,我们可以引入一些第三方库(
redis
、lru-cache
)来解决。
模块缓存是 Node.js 提供的一种包加载的机制,以提高开发过程中寻包的效率,而内存缓存和数据缓存则是业务层面的一种设计。
8、线程池
线程池由 libuv
库处理。libuv
是一个多平台 C 库,它支持基于异步 I/O 的操作,例如文件系统、网络和并发。通过线程池可以实现并发处理,提高系统的吞吐量和响应能力。
线程池利用计算机逻辑核的并行处理能力来执行多个任务,合理配置线程池的大小可以充分利用计算机的多核处理能力,提高系统的并发性和性能。
Node.js是基于单线程事件循环的,但是它使用线程池来处理某些任务,例如CPU密集型操作或需要进行阻塞式I/O的任务。线程池允许Node.js同时执行多个阻塞式操作,而不会阻塞事件循环本身。
当Node.js需要执行阻塞式I/O或CPU密集型操作时,它会将这些任务委派给线程池中的线程进行处理。这些线程对于Node.js来说是透明的,它们会在后台进行处理,并在完成后将结果返回给事件循环。这样,事件循环就不会被阻塞,其他请求仍然可以得到及时处理和响应。
总结起来,Node.js通过事件循环和线程池的机制实现了高效的并发处理。事件循环通过非阻塞I/O的方式处理大量并发请求,而线程池可以处理一些需要阻塞式I/O或CPU密集型操作的任务,以保持事件循环的高效运行。
三、内置变量
1、global
Node.js 中的 Global 全局对象,它是所有全局变量的容器
2、__dirname
__dirname
与 require 类似,都是 Node.js 环境中的'全局'变量
__dirname
保存着 当前文件所在目录的绝对路径 ,可以使用 __dirname
与文件名拼接成绝对路径
代码示例:
let data = fs.readFileSync(__dirname + "/data.txt");
console.log(data);
使用 fs
模块的时候,尽量使用 __dirname
将路径转化为绝对路径,这样可以避免相对路径产生的 bug
3、__filename
__dirname
保存着 当前文件的绝对路径。例如:在 目录下执行该文件 node example.js
console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr
四、主要的内置模块
以下是几个常用的模块:
fs
:文件系统模块,用于文件的读取、写入、创建、删除等操作,以及文件夹的创建和删除。path
: 路径处理模块,用于处理和转换指定的文件路径。http
:HTTP 模块,用于创建 HTTP 服务器,处理 HTTP 请求。https
:HTTPS 模块,用于创建 HTTPS 服务器。events
:事件模块,用于 Node.js 事件模型的核心,用于触发和处理事件。stream
:流模块,用于流式数据处理。url
:URL 处理模块,用于解析 URL 字符串。util
:实用工具模块,包含一些常用的工具函数,如util.promisify()
等。zilb
:压缩模块,用于实现 Gzip 和 Deflate/Inflate 算法。os
:操作系统 用于获取系统信息,如 CPU 、线程和内存使用情况。crypto
:加密模块,用于常见的加密、解密、签名、验证等算法的相关操作。
更新日志
e7112
-1于