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

使用http.get(...)时如何处理ETIMEDOUT错误?

问题:http.get的ETIMEDOUT错误无法被try-catch捕获

使用Node.js的http.get()发起请求时遇到ETIMEDOUT错误,尝试用try-catch包裹请求代码段,但无法捕获该错误,报错信息如下:

Concurrent Response #3 returned a 200
Concurrent Response #2 returned a 200
Concurrent Response #4 returned a 200
Concurrent Response #0 returned a 200
events.js:352
      throw er; // Unhandled 'error' event
      ^

Error: connect ETIMEDOUT 3.94.154.124:80
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1148:16)
Emitted 'error' event on ClientRequest instance at:
    at Socket.socketErrorListener (_http_client.js:475:9)
    at Socket.emit (events.js:375:28)
    at emitErrorNT (internal/streams/destroy.js:106:8)
    at emitErrorCloseNT (internal/streams/destroy.js:74:3)
    at processTicksAndRejections (internal/process/task_queues.js:82:21) {
  errno: -4039,
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '3.94.154.124',
  port: 80
}

原代码:

function sendRequest(requestID, cb) {
  var delay = Math.floor(Math.random() * (6 - 3 + 1)) + 5;
  var request = {
    hostname: "httpbin.org",
    headers: { "request-id": requestID },
    path: "/delay/." + delay,
  };
  require("http")
    .get(request, (res) => {
      var body = "";
      res.on("data", function (chunk) {
        body += chunk;
      });
      res.on("end", function () {
        cb(res, body);
      });
    })
    .end();
}

concurrentRequests(5);
function concurrentRequests(limit) {
  for (var i = 0; i < limit; i++) {
    sendRequest(i, function (res, body) {
      var reqID = JSON.parse(body).headers["Request-Id"];
      var sCode = res.statusCode;
      console.log("Concurrent Response #" + reqID + " returned a " + sCode);
    });
  }
}
原因与解决方法

try-catch无法捕获该错误的核心原因是:http.get()是异步操作,网络错误会以事件的形式触发,而非抛出同步异常。Node.js中如果异步事件的error没有被监听,就会导致未捕获异常崩溃。

解决方法是给http.get()返回的ClientRequest实例添加error事件监听器,处理超时等网络错误:

修改后的代码:

function sendRequest(requestID, cb) {
  var delay = Math.floor(Math.random() * (6 - 3 + 1)) + 5;
  var request = {
    hostname: "httpbin.org",
    headers: { "request-id": requestID },
    path: "/delay/." + delay,
  };
  require("http")
    .get(request, (res) => {
      var body = "";
      res.on("data", function (chunk) {
        body += chunk;
      });
      res.on("end", function () {
        cb(null, res, body); // 成功时第一个参数传null
      });
    })
    .on('error', (err) => {
      // 捕获并处理错误,比如回调给上层
      cb(err);
      console.error(`Request #${requestID} failed:`, err.message);
    })
    .end();
}

concurrentRequests(5);
function concurrentRequests(limit) {
  for (var i = 0; i < limit; i++) {
    sendRequest(i, function (err, res, body) {
      if (err) {
        // 处理错误情况
        return;
      }
      var reqID = JSON.parse(body).headers["Request-Id"];
      var sCode = res.statusCode;
      console.log("Concurrent Response #" + reqID + " returned a " + sCode);
    });
  }
}

关键修改点:

  • 为http.get()返回的请求对象添加.on('error', ...)监听器,捕获网络错误
  • 调整回调函数的参数,增加错误参数(遵循Node.js回调惯例:第一个参数为错误,成功时为null)
  • 在回调中判断是否有错误,进行对应处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:06:29