{T}

Node.js v22 原生能力实战:WebSocket + fetch + node:sqlite 协作看板

Node.js v22 在「去第三方依赖」方向上迈出关键一步:内置 WebSocket 客户端、fetch(稳定)、以及实验性 node:sqlite 同步 API。本实战用零运行时依赖构建一个实时协作看板——所有连接通过服务端原生 WebSocketServer 广播,任务持久化到 node:sqlite,外部数据经 fetch 聚合。

架构全景

图表渲染中…

1. 服务端骨架(v22 ESM)

js
import { WebSocketServer } from 'node:http';
import { sqlite3 } from 'node:sqlite';
import { createServer } from 'node:http';

const db = new sqlite3(':memory:');
db.exec(`CREATE TABLE tasks(id INTEGER PRIMARY KEY, title TEXT, done INTEGER)`);

const server = createServer();
const wss = new WebSocketServer({ server });

wss.on('connection', (ws) => {
  ws.on('message', (raw) => {
    const msg = JSON.parse(raw.toString());
    if (msg.type === 'add') {
      db.prepare('INSERT INTO tasks(title, done) VALUES(?, 0)').run(msg.title);
    }
    const tasks = db.prepare('SELECT * FROM tasks').all();
    const payload = JSON.stringify({ type: 'sync', tasks });
    for (const c of wss.clients) c.send(payload); // 广播一致性
  });
});

server.listen(3000);

2. 客户端实时同步

js
const ws = new WebSocket('ws://localhost:3000');
ws.onmessage = (e) => {
  const { tasks } = JSON.parse(e.data);
  render(tasks); // 全量重渲染,保持各端最终一致
};
document.querySelector('#add').onclick = () =>
  ws.send(JSON.stringify({ type: 'add', title: input.value }));

3. 通过 fetch 聚合外部数据

js
const res = await fetch('https://api.example.com/weather');
const { temp } = await res.json();
db.prepare('INSERT INTO tasks(title, done) VALUES(?, 0)').run(`天气播报:${temp}℃`);

关键工程要点

  • 广播顺序一致性:写入 SQLite 后再广播,避免客户端状态落后于持久层。
  • WebSocket 生命周期connection 后需监听 close 清理定时器/会话。
  • node:sqlite 同步阻塞:v22 仍为同步 API,高并发写入建议放入 Worker 线程(见 14-编译与底层原理 线程池篇)。
  • fetch 超时:原生 fetch 支持 AbortSignal.timeout(3000),防止外部 API 拖垮看板。

何时用原生能力 vs 第三方

能力原生(v22)第三方(ws/sequelize/axios)
WebSocket 服务端✅ 内置复杂场景用 ws
HTTP 客户端✅ fetch 稳定需拦截器用 axios
数据库⚠️ sqlite 实验期生产用 better-sqlite3