前端工程化 · 60/90
1. Babel 的工作原理 2. body-parser 中间件的作用 3. Babel 转译原理 4. 浏览器和 Node 中的事件循环区别 5. 职责链模式 6. 链模式 7. 命令模式 8. 组件封装设计 9. 数据统计 10. dependencies 和 devDependencies 的区别 11. CommonJS 和 ES6 模块引入的区别 12. 设计模式分类 13. 前端开发中常用的设计模式 14. 设计模式应用场景 15. 设计原则 16. 开发环境搭建要点 17. Electron 理解 18. 前后端分离是什么 19. 工厂模式 20. 前端代码重构 21. 前端组件化 22. 前端工程师职业发展 23. 前端工程化方向 24. 前端工程化的理解 25. 前端工程价值体现 26. 前端工程化 27. Git 常用命令与工作流 28. Gulp 任务自动化工具 29. 图片导出 30. 前端模块化规范 31. 迭代器模式 32. JavaScript 编码规范 33. 前端 CI/CD 流程 34. jQuery 生态对比 35. jQuery 实现原理 36. jQuery 与 Sizzle 选择器集成 37. Koa 中间件异常处理 38. jQuery 源码优秀实践 39. jQuery 与 Zepto 对比 40. jQuery UI 自定义组件 41. Koa 中间件不调用 await next() 的影响 42. Koa 在没有 async/await 时如何实现洋葱模型 43. Koa 和 Express 的区别 44. Koa 洋葱模型 45. 登录实现 46. 中介者模式 47. 模块模式 48. 小程序架构 49. 小程序常见问题 50. Monorepo 概念与工具 51. mpvue 框架 52. MVC vs MVP vs MVVM 53. Node.js ES Module 为什么必须加文件扩展名 54. MVC、MVP 和 MVVM 架构模式 55. Node.js 全局对象 56. Node.js 性能监控与优化 57. Node.js 多进程与进程通讯 58. Node.js 调试方法 59. Node.js 中的 process 对象 60. Node.js 的理解与应用场景 61. npm 是什么? 62. 观察者模式和发布订阅模式的区别 63. 页面重构方法 64. PM2 守护进程原理 65. 分页功能的前后端设计 66. PostCSS 作用 67. 项目管理方法 68. Rollup 打包工具 69. 高质量前端代码 70. JavaScript 单例模式实现 71. SSG 静态网站生成 72. 模板方法模式 73. 设计模式的六大原则 74. Tree Shaking 原理 75. 用户授权信息获取流程 76. Vite 原理与性能优势 77. Web App vs Hybrid App vs Native App 78. Web 前端开发注意事项 79. Web APP 设计原则 80. Webpack 构建流程 81. Hash vs ChunkHash vs ContentHash 82. Webpack 热更新原理 83. Webpack Loader 与 Plugin 区别 84. webpack 的 module、bundle、chunk 是什么 85. Webpack Proxy 工作原理与跨域解决 86. webpack、rollup、parcel 的选择 87. WePy 与 mpvue 对比 88. WXML 和 WXSS 89. Webpack Scope Hoisting 90. Zepto 实现原理

Node.js 的理解与应用场景

Node.js 的核心特性、优缺点及适用场景分析

问题

如何理解 Node.js?它有哪些优缺点和应用场景?

解答

Node.js 是什么

Node.js 是一个开源、跨平台的 JavaScript 运行时环境。它在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞 I/O 模型来提高性能。

简单来说,Node.js 就是一个服务器端的、非阻塞式 I/O 的、事件驱动的 JavaScript 运行环境。

非阻塞异步

Node.js 采用非阻塞型 I/O 机制,在执行 I/O 操作时不会造成阻塞。当操作完成后,以事件的形式通知执行。

例如访问数据库时,代码会立即继续执行后面的逻辑,把数据库返回结果的处理放在回调函数中,从而提高程序执行效率。

// 非阻塞示例
const fs = require('fs');

// 读取文件不会阻塞后续代码
fs.readFile('data.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log('文件内容:', data);
});

console.log('继续执行其他代码');
// 输出顺序:先输出"继续执行其他代码",再输出文件内容

事件驱动

当有新请求进来时,请求会被压入事件队列。通过事件循环检测队列中的事件状态变化,如果检测到状态变化,就执行对应的处理代码(通常是回调函数)。

const EventEmitter = require('events');
const emitter = new EventEmitter();

// 注册事件监听
emitter.on('fileRead', (data) => {
  console.log('文件读取完成:', data);
});

// 触发事件
emitter.emit('fileRead', 'file content');

优点

处理高并发性能好:事件驱动和非阻塞 I/O 使 Node.js 在高并发场景下表现优异。

适合 I/O 密集型应用:应用运行时 CPU 占用率较低,大部分时间在做 I/O 读写操作(如数据库查询、文件操作、网络请求)。

缺点

由于 Node.js 是单线程,存在以下缺点:

不适合 CPU 密集型应用:大量计算会阻塞单线程,影响整体性能。

无法充分利用多核 CPU:单线程只能使用一个 CPU 核心。

可靠性较低:某个环节崩溃可能导致整个系统崩溃。

应用场景

Node.js 适合 I/O 密集、高并发但计算简单的场景:

实时应用:聊天室、图文直播、多人联网游戏、实时协作工具

API 服务:为前端和移动端提供 RESTful API、操作数据库

后台系统:用户表单收集、后台管理系统、考试系统

单页应用:配合前端框架的服务端渲染(SSR)

长连接应用:与 WebSocket 配合开发实时交互应用

// WebSocket 服务示例
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
  ws.on('message', (message) => {
    // 广播消息给所有客户端
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });
});

关键点

  • Node.js 基于事件驱动和非阻塞 I/O,适合高并发场景
  • 单线程模型使其适合 I/O 密集型应用,但不适合 CPU 密集型计算
  • 最佳应用场景是实时通信、API 服务和需要大量并发 I/O 的系统
  • 代码崩溃会影响整个系统,需要做好错误处理和进程管理
  • 可以通过 cluster 模块或 PM2 等工具实现多进程,充分利用多核 CPU