Node.js
Node.js 是基于 Chrome V8 引擎的 JavaScript 运行时,将 JS 的执行环境从浏览器扩展到服务端。核心特征是单线程事件循环 + 非阻塞 I/O,擅长处理高并发 I/O 密集型任务。
版本管理推荐使用 nvm,包管理可选 npm、yarn 或 pnpm。
安装
# 推荐:通过 nvm 安装,支持多版本切换
nvm install 22 # 安装 LTS 版本
nvm use 22
node --version # 验证
# 直接下载安装包(固定版本)
# https://nodejs.org/zh-cn/download/Node.js 版本分为:
- LTS(长期支持):生产环境首选,维护周期 30 个月
- Current:包含最新特性,适合尝鲜
事件循环
Node.js 的并发模型基于事件循环,单线程处理所有请求,I/O 操作委托给底层 libuv 异步执行:
┌───────────────────────┐
│ timers │ ← setTimeout / setInterval 回调
├───────────────────────┤
│ pending callbacks │ ← 上一轮 I/O 错误回调
├───────────────────────┤
│ idle, prepare │ ← 内部使用
├───────────────────────┤
│ poll │ ← 获取新 I/O 事件(核心阶段)
├───────────────────────┤
│ check │ ← setImmediate 回调
├───────────────────────┤
│ close callbacks │ ← socket.on('close') 等
└───────────────────────┘
微任务(Promise.then、queueMicrotask)在每个阶段切换前执行,优先级高于宏任务。
console.log('1');
setTimeout(() => console.log('setTimeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('2');
// 输出顺序:1 → 2 → Promise → setTimeout模块系统
CommonJS(CJS)— 传统方式
// 导出
const add = (a, b) => a + b;
module.exports = { add };
// 或
exports.add = add;
// 导入(同步,运行时解析)
const { add } = require('./math');
const fs = require('fs'); // 内置模块
const lodash = require('lodash'); // npm 包ES Modules(ESM)— 现代方式
// 文件扩展名用 .mjs,或 package.json 设置 "type": "module"
// 导出
export const add = (a, b) => a + b;
export default class Calculator { ... }
// 导入(静态,编译时解析;支持 Tree Shaking)
import { add } from './math.js';
import Calculator from './math.js';
// 动态导入(按需加载)
const { add } = await import('./math.js');.cjs 强制 CommonJS,.mjs 强制 ESM,package.json 中 "type": "module" 将 .js 默认为 ESM。
内置模块
fs — 文件系统
import { readFile, writeFile, readdir, stat, mkdir, unlink } from 'fs/promises';
// 读文件
const content = await readFile('./config.json', 'utf-8');
const config = JSON.parse(content);
// 写文件
await writeFile('./output.txt', 'Hello World', 'utf-8');
// 目录操作
const files = await readdir('./src');
await mkdir('./dist', { recursive: true }); // 递归创建
// 文件信息
const info = await stat('./package.json');
console.log(info.size, info.mtime);
// 流式读取大文件(避免内存溢出)
import { createReadStream } from 'fs';
const stream = createReadStream('./large.csv', { encoding: 'utf-8' });
for await (const chunk of stream) {
process(chunk);
}path — 路径处理
import path from 'path';
path.join('/foo', 'bar', 'baz.txt') // '/foo/bar/baz.txt'(跨平台)
path.resolve('src', 'index.js') // 返回绝对路径
path.dirname('/foo/bar/baz.txt') // '/foo/bar'
path.basename('/foo/bar/baz.txt') // 'baz.txt'
path.extname('index.html') // '.html'
// ESM 中获取当前文件目录(替代 __dirname)
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));http / https — 原生 HTTP 服务
import http from 'http';
const server = http.createServer((req, res) => {
if (req.method === 'GET' && req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
return;
}
res.writeHead(404);
res.end('Not Found');
});
server.listen(3000, () => console.log('Server running on :3000'));实际项目通常使用 Express / Koa / Fastify 等框架,而非直接使用原生 http 模块。
events — 事件发射器
import { EventEmitter } from 'events';
class DownloadTask extends EventEmitter {
async start(url) {
this.emit('start', url);
try {
const data = await fetch(url);
this.emit('progress', 50);
// ... 处理数据
this.emit('done', data);
} catch (err) {
this.emit('error', err);
}
}
}
const task = new DownloadTask();
task.on('start', (url) => console.log('开始下载:', url));
task.on('progress', (pct) => console.log(`进度: ${pct}%`));
task.on('done', (data) => console.log('完成'));
task.on('error', (err) => console.error('失败:', err));crypto — 加密
import crypto from 'crypto';
// 哈希
const hash = crypto.createHash('sha256').update('password').digest('hex');
// HMAC 签名
const sign = crypto.createHmac('sha256', 'secret').update('data').digest('hex');
// 生成随机 Token
const token = crypto.randomBytes(32).toString('hex');
// UUID v4
const { randomUUID } = crypto;
const id = randomUUID(); // 'a1b2c3d4-...'child_process — 子进程
import { exec, execFile, spawn } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
// 执行 shell 命令(小输出)
const { stdout } = await execAsync('git log --oneline -5');
console.log(stdout);
// spawn 处理大输出(流式)
const child = spawn('node', ['worker.js']);
child.stdout.on('data', (data) => console.log(data.toString()));
child.on('close', (code) => console.log(`退出码: ${code}`));全局对象
// 进程信息
process.env.NODE_ENV // 环境变量
process.argv // 命令行参数([node, script, ...args])
process.cwd() // 当前工作目录
process.exit(0) // 退出进程
process.on('uncaughtException', handler) // 全局异常捕获
// 计时器
setTimeout(fn, 1000)
setInterval(fn, 1000)
setImmediate(fn) // 当前事件循环末尾执行
queueMicrotask(fn) // 微任务队列
// 全局对象(ESM 中可用)
globalThis.myVar = 'shared';错误处理
// 异步函数统一 try/catch
async function fetchUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('fetchUser 失败:', err.message);
throw err; // 向上传播,不要静默吞掉
}
}
// 未捕获的 Promise 异常
process.on('unhandledRejection', (reason, promise) => {
console.error('未处理的 Promise 拒绝:', reason);
process.exit(1);
});
// 同步未捕获异常
process.on('uncaughtException', (err) => {
console.error('未捕获异常:', err);
process.exit(1);
});Worker Threads(多线程)
Node.js 主线程单线程,CPU 密集型任务用 Worker 线程并行:
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads';
if (isMainThread) {
const worker = new Worker(import.meta.url, {
workerData: { numbers: [1, 2, 3, 4, 5] }
});
worker.on('message', (result) => console.log('结果:', result));
} else {
const sum = workerData.numbers.reduce((a, b) => a + b, 0);
parentPort.postMessage(sum);
}常用 CLI 命令
node index.js # 执行脚本
node --watch index.js # 文件变更自动重启(Node 18+)
node -e "console.log(1+1)" # 执行单行代码
node --inspect index.js # 启用调试器(配合 Chrome DevTools)
# 查看版本
node --version
node -v
# REPL 交互环境
node
> 2 + 2
4