node.js - 强制 API 超时时节点 JS 中的套接字挂断错误
问题描述
我在 Node JS (v8.12) 中使用请求模块来调用第三方 API。由于 API 不是很可靠并且由于缺乏更好的选项,我会在 2 秒后超时调用,以防 API 没有响应。但是这样做会产生一个套接字挂起错误。下面是使用的代码和堆栈跟踪
const options = {
url: resource_url,
rejectUnauthorized: false,
timeout: 2000,
method: 'GET',
headers: {
'content-Type': 'application/json',
}
};
return new Promise(function (resolve, reject) {
request(options, function (err, res, body) {
if (!err) {
resolve(JSON.parse(body.data));
} else {
if (err.code === 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
resolve(someOldData);
} else {
resolve(someOldData);
}
}
});
});
Error: socket hang up
at createHangUpError (_http_client.js:331:15)
at TLSSocket.socketCloseListener (_http_client.js:363:23)
at scope.activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:54:19)
at Scope._activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/async_hooks.js:51:14)
at Scope.activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:12:19)
at TLSSocket.bound (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:53:20)
at emitOne (events.js:121:20)
at TLSSocket.emit (events.js:211:7)
at _handle.close (net.js:554:12)
at TCP.done [as _onclose] (_tls_wrap.js:356:7)
在做了一些阅读和研究之后,我发现这篇文章指出了一个类似的问题,所以我切换到了 http 模块,正如文章中的一个解决方案中提到的那样。但是切换到 http 模块也没有解决问题。下面是使用 http 和堆栈跟踪的代码实现。
let responseData;
const requestOptions = {
hostname: resource_host,
path: resource_path,
method: 'GET',
timeout: 2000,
};
return new Promise((resolve, reject) => {
const requestObject = http.request(requestOptions, (responseObj) => {
responseObj.setEncoding('utf8');
responseObj.on('data', (body) => {
responseData = body;
});
responseObj.on('end', () => {
resolve(responseData);
});
});
requestObject.on('error', (err) => {
responseData = someOldData;
resolve(responseData);
});
requestObject.on('timeout', () => {
responseData = someOldData;
requestObject.abort();
});
requestObject.end();
});
Error: socket hang up
at connResetException (internal/errors.js:608:14)
at Socket.socketCloseListener (_http_client.js:400:25)
at <trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:54:19
at Scope._activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/async_hooks.js:51:14)
at Scope.activate (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:12:19)
at Socket.bound (<trace-log-base-path>/dd-trace/packages/dd-trace/src/scope/base.js:53:20)
at Socket.emit (events.js:322:22)
at Socket.EventEmitter.emit (domain.js:482:12)
at TCP.<anonymous> (net.js:672:12)
我通过网络浏览了多个 SO 帖子和各种其他资源,但我无法解决这个问题。
可能是因为第三方,因为我还尝试通过创建一个虚拟服务器来重现该问题,该服务器在请求被触发后休眠一段时间并超时该请求但无法重现该问题。
我将非常感谢在这方面的任何帮助。
解决方案
使用 http 模块时删除超时事件块中的requestObject.abort()可解决此问题。
推荐阅读
- excel - 使用命令行和参数启动 Excel
- c# - 带有全选复选框的Angular js网格删除记录
- javascript - 如何将键盘笔划分配给按钮?
- scala - 如何从 sbt-coveralls 迁移到 GitHub Actions?
- javascript - 使用 validate.js 验证我的 TextInput 导致未定义
- javascript - 无法在 JavaScript 类中使用 this 获取值?
- python - 在 Ubuntu 上安装了 Python 3.8,但不是默认的
- rust - 如何将 Rust 向量中的元素向右移动并将越界元素放在开头?
- javascript - SocketIO 以突发方式而不是连续方式传输数据
- java - 在 Keycloak 中实现执行操作电子邮件的接口