Skip to content

第 4 章:核心模块实战 ​

Node 自带一套精悍的核心模块,fs、path、http、stream 是日常开发四大件。这一章用真实代码讲清它们的用法。


4.1 fs:文件系统 ​

所有文件操作都在 fs 模块里。它同时提供回调版、Promise 版、同步版三套 API:

javascript
const fs = require('fs');           // 回调版
const fsp = require('fs/promises'); // Promise 版(推荐)

// 同步版:会阻塞主线程,只用于启动时加载配置
const config = fs.readFileSync('config.json', 'utf8');

// Promise 版:日常开发首选
await fsp.readFile('data.txt', 'utf8');      // 读
await fsp.writeFile('data.txt', '内容');      // 写(覆盖)
await fsp.appendFile('log.txt', '一条日志\n'); // 追加
await fsp.mkdir('dir/sub', { recursive: true }); // 建目录(recursive 自动建父级)
await fsp.rm('dir', { recursive: true, force: true }); // 删除(force 忽略不存在)

选择原则:能用 fs/promises 就用它(配合 async/await);readFileSync 这类同步方法只用在启动初始化阶段。


4.2 path:路径处理 ​

跨平台路径处理用 path,不要手拼字符串(Windows 用 \,Linux 用 /):

javascript
const path = require('path');

path.join('src', 'utils', 'tool.js');    // src/utils/tool.js(自动加分隔符)
path.resolve('src', 'tool.js');          // 转成绝对路径
path.dirname('/a/b/c.js');               // /a/b
path.basename('/a/b/c.js');              // c.js
path.extname('/a/b/c.js');               // .js
path.parse('/a/b/c.js');                 // { dir, base, ext, name } 拆解

技巧:path.join(__dirname, 'data.json') 是基于「当前文件所在目录」定位资源,这是最稳的相对路径写法。


4.3 http:起一个服务器 ​

用原生 http 模块起服务,理解底层原理:

javascript
const http = require('http');

const server = http.createServer((req, res) => {
  // req 请求对象,res 响应对象
  const { method, url } = req;

  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ method, url }));
});

server.listen(3000, () => {
  console.log('服务已启动 http://localhost:3000');
});
浏览器 ──HTTP请求──► Node http server ──► 你的回调 (req, res)
  ▲                                              │
  └────────────HTTP响应 ◄──── res.end(内容) ◄─────┘

核心概念:

  • req:请求,含 method(GET/POST)、url、headers,POST 的 body 要手动接收;
  • res:响应,writeHead 设状态码/头,end 发送内容并结束。

4.4 stream:流式处理 ​

流是 Node 最强大的特性之一,用来边读边处理大数据,而不是一次性全部载入内存:

【一次性读取】1GB 文件 ──► 全部读进内存 ──► 处理(内存爆了)
【流式读取】  1GB 文件 ──► 一块一块流进来 ──► 边读边处理(内存恒定)

四种流:

类型作用例子
Readable可读流fs.createReadStream
Writable可写流fs.createWriteStream
Duplex双工流net.Socket
Transform转换流zlib.createGzip

管道(pipe)串联——文件复制、压缩、转发,一条管道搞定:

javascript
const fs = require('fs');
const zlib = require('zlib');

// 读文件 → gzip 压缩 → 写文件
fs.createReadStream('big.log')
  .pipe(zlib.createGzip())     // 转换流:压缩
  .pipe(fs.createWriteStream('big.log.gz'));
可读流 ──pipe──► 转换流 ──pipe──► 可写流
(读文件)   │     (压缩/加密)  │    (写文件)
           └────── 数据块流动 ──────┘

事件监听(不 pipe 时手动处理):

javascript
const rs = fs.createReadStream('big.log', { encoding: 'utf8' });
rs.on('data', chunk => console.log('一块', chunk.length));
rs.on('end', () => console.log('读完了'));
rs.on('error', err => console.error('出错', err));

实战意义:处理大文件、转发请求/响应、上传下载、对接大模型的流式输出,全都靠 stream。第 6 章会看到流式接收大模型响应的完整应用。


4.5 本章小结 ​

模块用途要点
fs文件读写优先 fs/promises,同步版只用于启动初始化
path路径处理path.join 跨平台,__dirname 定位资源
httpHTTP 服务createServer + (req, res),理解请求响应模型
stream流式处理边读边处理,pipe 管道串联,是大数据/流式输出基石

下一章预告 ​

原生 http 写路由太繁琐,实战都会上框架。Express 的中间件「洋葱模型」是怎么回事?Koa 又有什么不同?

👉 第 5 章:HTTP 服务与中间件

📖本文阅读--次|📊全站访问--次|👥访客--人