Node.js开发
Node.js 是基于 Chrome V8 引擎的 JavaScript 运行时,让 JavaScript 突破浏览器限制运行在服务端。它由 Ryan Dahl 于 2009 年发布,核心设计是"单线程 + 事件循环 + 非阻塞 I/O":一个线程处理所有请求,遇到 I/O 不干等,注册回调后继续干活。这个模型让 Node.js 在高并发 I/O 密集型场景下用极少的资源吃掉海量请求,但 CPU 密集型任务会阻塞事件循环——选型时要分清边界。
提示
Node.js 的定位一句话:I/O 密集选它,CPU 密集绕开它。Web 服务、API 网关、实时推送、命令行工具是它的主场;图像处理、视频编码、机器学习请交给多线程/子进程或其他语言。
事件循环
事件循环是 Node.js 的调度核心:单线程不断轮询各阶段的任务队列,I/O 完成的事件在对应阶段被取出执行。一个事件循环迭代(tick)经过以下阶段:
| 阶段 | 处理什么 | 典型场景 |
|---|---|---|
| timers | 定时器到期回调 | setTimeout、setInterval |
| poll | 网络/文件 I/O 完成回调 | 读文件、HTTP 请求的回调大多在这里执行 |
| check | 立即执行回调 | setImmediate |
| close | 资源关闭回调 | socket 关闭、流结束 |
微任务与宏任务
Promise.then、process.nextTick 属于微任务,不进入上述阶段队列,而是在当前阶段结束前插队执行——所以 Promise 回调永远比下一个阶段的 setTimeout 先跑。理解"宏任务按阶段轮询、微任务阶段内插队",是预测异步代码执行顺序的关键。
setTimeout(() => console.log('1 timers'), 0);
Promise.resolve().then(() => console.log('2 microtask'));
setImmediate(() => console.log('3 check'));
// 输出顺序:2 microtask → 1 timers → 3 check
// (微任务优先于下一个宏任务;check 晚于 timers)代码规范
Node.js/JavaScript 项目的通用规范:
| 规范 | 说明 |
|---|---|
| 缩进 | 2 空格 |
| 分号 | 语句结尾加 ;(避免 ASI 自动插入的歧义) |
| 变量声明 | 默认 const,需要重赋值用 let,禁用 var |
| 字符串 | 优先单引号(或统一按 Prettier 配置) |
| 命名 | 变量/函数 camelCase,类 PascalCase,常量 UPPER_SNAKE |
| 异步 | 统一 async/await,禁止回调地狱 |
用工具保证规范
手写规范靠自觉,落地靠工具:Prettier 管格式(npx prettier --write .),ESLint 管代码质量(npx eslint .),两者配置进 package.json 的 scripts 后,npm run lint 一键检查。
错误处理
Node.js 的错误分两类,处理方式不同:
// 同步错误:try/catch 直接捕获
try {
JSON.parse('invalid');
} catch (err) {
console.error(err);
}
// 异步错误:Promise/async 的 catch(详见 [[异步编程]] 的错误处理)
process.on('unhandledRejection', (err) => {
console.error('未捕获的 Promise 拒绝:', err);
});进程崩溃防护
同步代码抛出的未捕获异常(uncaughtException)会让进程直接退出——生产环境应避免"监听后继续运行"的写法,正确做法是记录错误后优雅重启(如 PM2 的自动重启机制)。日志系统是定位线上问题的关键,见 Linux日志系统 的服务端视角。
性能测试
用 benchmark 库做基准测试,量化"哪种写法更快":
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();
suite
.add('for loop', function() {
let sum = 0;
for (let i = 0; i < 1000; i++) { sum += i; }
})
.add('while loop', function() {
let sum = 0, i = 0;
while (i < 1000) { sum += i++; }
})
.on('cycle', (event) => console.log(String(event.target)))
.on('complete', function() {
console.log('Fastest: ' + this.filter('fastest').map('name'));
})
.run({ async: true });性能优化的正确顺序
先测再优化:用 --prof 或 clinic 找到热点,再针对热点优化;不要凭感觉优化(V8 的 JIT 行为经常反直觉)。I/O 密集场景优先检查:是否用了 Promise.all 并发、是否阻塞了事件循环、是否重复创建了连接。
适用场景
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| Web API 服务 | Express + async/await | 中间件模式,生态成熟 |
| 实时应用 | Socket.io + 事件驱动 | 非阻塞 I/O,高并发长连接 |
| 命令行工具 | Node.js 原生 | 跨平台,npm 生态丰富 |
| 前端构建 | Vite/Webpack | 构建工具基于 Node.js |
| 不适合 | 图像处理、机器学习 | 单线程会阻塞事件循环,用 Worker Threads 或换语言 |
npm包管理 管依赖、异步编程 管并发写法、作用域与闭包 管语言底层规则、正则表达式 管文本处理——它们合起来构成 Node.js 开发的知识底座,详见 JavaScript 的领域地图。