使用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
相关产品推荐
相关产品推荐

