Node.js Web 模块

http/https 客户端、fetch、WebSocket、以及服务端与客户端两侧。

Intermediate
Key PointsNode 18+ 用内置 `fetch` 发请求;需要细粒度控制时用 `http.request`。

服务端与客户端

RoleAPITypical use
服务端http.createServer接收请求
客户端fetch调第三方 API
客户端http.request需要控制 header/超时/流
双向WebSocket(需 ws 包)实时推送

fetch

JavaScript
// GET
const res = await fetch('https://api.github.com/repos/nodejs/node');
console.log(res.status);
const repo = await res.json();
console.log(repo.stargazers_count);

// POST JSON
const created = await fetch('https://httpbin.org/post', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'tom' }),
  signal: AbortSignal.timeout(5000),
});
console.log(await created.json());
Output
200
107324
{ ... "json": { "name": "tom" } ... }

fetch rejects only on network failures. HTTP 404 and 500 count as success, so check res.ok yourself. This is the easiest thing to forget when migrating from axios.

http.request

JavaScript
const https = require('node:https');

function get(url) {
  return new Promise((resolve, reject) => {
    const req = https.get(url, { timeout: 5000 }, (res) => {
      if (res.statusCode !== 200) {
        res.resume();                       // 丢弃响应体,释放连接
        return reject(new Error(`HTTP ${res.statusCode}`));
      }
      let data = '';
      res.setEncoding('utf8');
      res.on('data', (c) => (data += c));
      res.on('end', () => resolve(JSON.parse(data)));
    });
    req.on('timeout', () => req.destroy(new Error('超时')));
    req.on('error', reject);
  });
}
When the status is not 200, **always call res.resume()** — otherwise the body is never drained, the socket is not released, and the connection pool fills up. The most hidden http.request trap.

并发请求

JavaScript
const urls = ['https://a.com/1', 'https://a.com/2', 'https://a.com/3'];

// 全部并发
const all = await Promise.all(urls.map((u) => fetch(u).then((r) => r.text())));

// 限制并发为 2
async function pool(tasks, limit) {
  const results = [];
  const running = new Set();

  for (const task of tasks) {
    const p = task().finally(() => running.delete(p));
    running.add(p);
    results.push(p);
    if (running.size >= limit) await Promise.race(running);
  }
  return Promise.all(results);
}

WebSocket

JavaScript
// npm i ws
const { WebSocketServer } = require('ws');

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws) => {
  ws.send('欢迎');
  ws.on('message', (msg) => {
    // 广播给所有人
    for (const c of wss.clients) {
      if (c.readyState === c.OPEN) c.send(msg.toString());
    }
  });
});

console.log('ws://127.0.0.1:8080');
Output
ws://127.0.0.1:8080

Friends & Partners