一、什么是 Node.js

1、前言

接触 node.js 有好几年了,也开发了好几个项目了;但每次提起 node.js,始终不敢说自己入门了,归其原因,大概就是如下所示

为了进一步加强理解,系统的梳理相关知识以作备忘,本节将从以下几个方面介绍 node.js

  • 为什么前端需要掌握?
  • 什么是 node.js?

1.1、为什么前端需要掌握

Node.js 单线程高并发的特性非常适合用来创建后端服务;虽然但是,好像不会使用 Node.js 根本不影响我写前端页面嘛~。

no no no ,作为一个新时代的三有前端,要本着知其然并知其所以然的精神彻底掌握 Node.js,因为它不仅仅是用来写后端,更重要的用途是提升我们项目工程化和效率。

  • 操作文件系统;在日常开发,经常会涉及到文件夹操作;比如某个需求,给你几百个资料,需要你做成资料下载页,妈妈呀,手都要复制麻了,赶紧写一个 DOS 批处理命令,尴尬了,还是上学那会学过一点,早忘了七七八八了;不慌,Node.js 来帮忙,fs 模块轻松解决。
  • 开发自己的命令行工具;典型的就是 vue2 store 中在仓库增加一项,需要同时在 state、mutation、action 增加对应的模型操作,非常繁琐,如果你掌握了 Node.js,就可以开发一个自己的命令,一键添加。
  • 编写打包脚本工具,如 webpack 的 loader,嘿嘿,这个熟悉吧
  • 发布自己的 npm 包,搭建各项目通用基座,告别 Ctrl + C、V
  • 实现自己的脚手架,再也不用整一个模板项目然后每次复制了

你自己也会写 npm 包、脚手架、打包脚本了,是不是很受诱惑,嘿嘿...

2、node.js 的概念和特性

Node官网对其进行了简单的不能再简单的描述

Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。

翻阅官网教程,大致对其概念和特性有了一些认识:

  • Node.js 是一个服务端运行环境,它使用 Google 的 V8 虚拟机来解释和执行 JavaScript 代码。
  • Node.js 同时又是一个库,具有许多有用的模块,可以简化操作。
  • 当 Node.js 执行 I/O 操作时,如从网络读取、访问数据库或文件系统,Node.js 不会阻塞线程,而是通过事件回调机制来完成回调处理。
  • Node.js 应用在单个进程中运行,无需为每个请求创建新线程,这使得 Node.js 在构建高并发应用时非常得心应手(如实时聊天、秒杀、抢购等)。

2.1 Node.js VS 浏览器

同样是解析 JavaScript,为啥 Node.js 与浏览器的功能差别这么大?

在 Node.js 之前,JavaScript 主要运行在浏览器宿主环境中,主要是操作 DOM、BOM,浏览器提供了 document、window 等对象;

Node.js 则允许在服务端运行 JavaScript,不具有浏览器才有的 window、document 等对象,主要是操作磁盘文件、搭建 http 服务等等等等...

这么牛逼?提供各种模块,还能在各大平台运行的飞起,这是我了解的 JavaScript?其本质不是 JavaScript 有多牛逼,而是它封装了许多强大的依赖,以下是 Node 源码的依赖列表

最典型的依赖就是 v8 和 uv

  • v8 引擎: 将 js 代码转变成可以在各个平台和机器上运行的机器码
  • libuv:C 语言编写的库,调用平台上的各种系统特性,如文件系统;同时负责 Node API 的执行,它将不同的任务分配给不同的工作线程(work threads),通过多线程同步阻塞执行,模拟异步处理机制,成功后将回调函数放入 Event Queue
  • npm: Node.js 包管理和分发工具,提供各种非官方的 Node 模块

上图是 libuv 大致的结构,很明显,Node.js 的网络 I/O、文件 I/O、DNS 操作、还有一些用户代码都是在 libuv 工作的

2.2 异步 I/O

libuv 的存在,使得 Node.js 可以是单线程的。每当有 I/O 请求发生时,node 就会扔给 libuv,由 libuv 为该请求分配给不同的工作线程(libuv 默认维护 4 个线程供 Node 调用,可以通过 UV_THREADPOOL_SIZE 环境变量在 Node 启动时设置,为了性能,不能超过 128 个),同步阻塞性的执行,执行完成后将回调函数放入事件队列中。

而 node 则不会管这个 I/O 的操作过程,继续执行主线程上的事件,只需要在该请求返回回调时在处理即可,从而实现非阻塞性的异步 I/O 处理。

2.3 单线程&高并发

与 JavaScript 一样,Node 是单线程,它将阻塞性的操作丢给 libuv 提供的线程池。

单线程的优点:

  • 避免了多线程编程中可能出现的竞态条件、锁和死锁等问题,简化了编码过程
  • 由于每个线程都将暂用一定的内存,在服务器内存受限的情况下,具有更好的高并发

单线程的缺点:

  • 不适合大量计算,会占用 CPU 导致应用阻塞(在主线程上避免大量计算)
  • 错误会引起整个应用的退出(可以利用 pm2 或 nginx 来监测服务状态,自动重启)
  • 容易受到阻塞性操作的影响;Node 主线程上如果有同步阻塞性 I/O 操作,可能会导致阻塞,这也就要求我们尽可能的使用 Node.js 的异步编程,异步编程是 Node.js 的核心

2.3.1 线程和进程

概念:线程是进程内的最小执行单元。一个进程可以有一个或多个线程。所有线程共享该进程的地址空间和资源。

进程与进程之间相互独立,通讯困难;而线程与线程则共享进程的资源,通讯简单;

Node.js 本身运行在一个进程中,当我们说 Node.js 是单线程时,是指它在这个进程中只使用一个线程来执行 JavaScript 代码

Node.js 只有一个主线程,是单线程;但并不是说 Node 只支持单线程;如果想要创建新的线程,可以使用 Node.js 内置的 Worker threads 模块

如果想要创建新的进程,可以使用 Node.js 内置的 ClusterChild process 模块。

2.3.2 为什么单线程并发高?

传统的服务端语音中(如 Java),每一个客户端连接都会为其创建一个新的线程,而每个线程都需要一定的内存(1~2M),受服务器内存限制,成为了高并发连接的瓶颈。

Node.js 则只有一个线程,大大的节省了服务器内容,它通过为每一个用户连接在 Node.js 内部,触发一个事件,Node.js 高并发的特性使得它在构建在线聊天、秒杀、抢购等应用时具有非常大的优势.

当然,这是建立在内存受限的情况下,如果你有足够大的服务器内存;那么传统的服务端语言将拥有更快的响应速度,Node 的事件循环机制将可能出现等待,即主线程有同步阻塞任务,事件循环将被阻塞

2.4 事件循环

Node.js 通过异步回调来处理,那么 Node 如何知道请求或操作完成了添加回调;又是如何执行回调的?这是由于 Node.js 的另一特性:事件循环机制,主线程通过 Event Loop 事件循环触发的方式来运行程序

注意,Node.js 的事件循环与浏览器下 JavaScript 的事件循环机制是不一样的,具体参考浏览器事件循环 VS Node.js 事件循环

3、结束语

好消息:今天周三了

坏消息:今天才周三

按道理,我没记错的话,朋友,今天应该是周五的吧~

有多少软件工程的小伙伴被戳中了,哈哈

相关推荐
ldq_sd5 小时前
node.js安装和配置教程
node.js
我真的很困6 小时前
坤坤带你学浏览器缓存
前端·http·node.js
whyfail9 小时前
ESM 与 CommonJS:JavaScript 模块化的两大主流方式
javascript·node.js
熊的猫9 小时前
ES6 中 Map 和 Set
前端·javascript·vue.js·chrome·webpack·node.js·es6
Pigwantofly11 小时前
软件工程概论项目(二),node.js的配置,npm的使用与vue的安装
node.js
ZJ_.15 小时前
Electron 沙盒模式与预加载脚本:保障桌面应用安全的关键机制
开发语言·前端·javascript·vue.js·安全·electron·node.js
前端SkyRain15 小时前
后端Node学习项目-用户管理-增删改查
后端·学习·node.js
丁总学Java16 小时前
使用 npm 安装 Yarn
前端·npm·node.js
理想不理想v16 小时前
执行npm run build -- --report后,生产report.html文件是什么?
java·前端·javascript·vue.js·webpack·node.js
ForRunner12317 小时前
在 Node.js 中解决极验验证码:使用 Puppeteer 自动化
运维·node.js·自动化