You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Node.js HTTP模块处理跨服务API调用错误?

问题分析与解决方案

一、为什么getId接口抛错时,addUser仍会进入data事件回调?

你在Server2里直接throw new Error,但Express框架遇到未捕获的同步错误时,会默认返回500状态码的HTML错误页面,不会直接断开请求连接。这意味着Server1的HTTP请求并没有触发error事件(该事件仅在网络级错误,比如连接失败、DNS解析失败时触发),而是正常接收到了Server2返回的HTML响应数据——所以res.on('data')会被触发,尝试把HTML内容解析成JSON,自然就会抛出语法错误。

二、正确的错误处理方式

1. 先修复Server2的错误返回格式

让Server2在出错时返回JSON格式的错误信息,而非默认的HTML,这样Server1能正确识别错误:

// Server2 修改后的代码
app.get('/api/getId', (req, res) => {
  // 主动返回JSON错误,替代直接throw
  res.status(500).json({ error: 'getId api error' });
});

// 或者用Express全局错误中间件捕获所有未处理的错误
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message });
});

2. Server1端的完整错误处理优化

针对HTTP请求和数据解析环节,需要做好以下几点:

  • 处理流式数据拼接:data事件可能多次触发(数据分块传输),必须拼接所有数据后再解析
  • 检查响应状态码:先判断响应状态码是否在成功范围(2xx),非成功状态直接处理错误
  • 捕获JSON解析异常:用try-catch包裹JSON.parse,避免解析失败导致进程崩溃
  • 完善错误监听:同时监听请求的error事件和响应的error事件
  • 设置请求超时:避免请求长时间挂起

修改后的Server1代码:

// Server1 修改后的代码
app.get('/api/addUser/:userName', (req, res) => {
  const options = {
    host: 'localhost',
    port: 3090,
    path: '/api/getId',
    method: 'GET',
    headers: {
      accept: 'application/json'
    },
    timeout: 5000 // 设置5秒超时
  };

  const reqToServer2 = http.request(options, (server2Res) => {
    // 先判断响应状态码
    if (server2Res.statusCode < 200 || server2Res.statusCode >= 300) {
      errorCounter.add(1);
      return res.status(500).json({ error: `Server2返回错误状态码:${server2Res.statusCode}` });
    }

    let rawData = '';
    // 拼接分块数据
    server2Res.on('data', (chunk) => {
      rawData += chunk;
    });

    // 数据接收完成后处理
    server2Res.on('end', () => {
      try {
        const userId = JSON.parse(rawData);
        const user = {
          userName: req.params.userName,
          userId
        };
        users.push(user);
        res.json(user); // 给客户端返回成功响应
      } catch (parseErr) {
        errorCounter.add(1);
        res.status(400).json({ error: '解析Server2响应失败', details: parseErr.message });
      }
    });
  });

  // 监听请求错误(如连接失败、超时)
  reqToServer2.on('error', (err) => {
    errorCounter.add(1);
    res.status(500).json({ error: '请求Server2失败', details: err.message });
  });

  // 监听超时
  reqToServer2.on('timeout', () => {
    reqToServer2.destroy();
    errorCounter.add(1);
    res.status(504).json({ error: '请求Server2超时' });
  });

  reqToServer2.end();
});

关键优化点说明

  • 外层try-catch无法捕获http.request回调里的异步错误,所以移除了无效的外层捕获逻辑
  • 把数据解析逻辑移到end事件,确保处理的是完整的响应数据
  • 针对不同错误场景(网络错误、状态码错误、解析错误、超时)分别处理,更新错误计数器并返回明确的错误信息

内容的提问来源于stack exchange,提问作者bunny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:01:54