javascript - 正确处理长时间运行的请求中的 HTTP 连接生命周期
问题描述
我在使用端点时启动了一个繁重的 I/O 进程。该端点应立即响应客户端该进程已启动。
繁重的 I/O 任务可能需要长达 30 分钟,所以我想知道的是服务器和客户端之间的连接在什么状态下离开res.json(...)
?套接字连接是否仍然打开/半打开?在这种情况下,我应该在之后手动销毁套接字res.json(...)
吗?29heavyIO
分钟后任务失败并转到快速错误处理程序是否可以?最后;这种模式是否不正确,例如,我应该以完全不同的方式处理 I/O 任务吗?
下面是一个最小的例子:
import express from 'express'
const app = express()
const asyncHandler = (handler) =>
(req, res, next) => Promise.resolve(handler(req, res, next)).catch(next)
const heavyIO = () =>
new Promise((resolve, reject) => setTimeout(() => Math.random() > 0.5 ? resolve() : reject('FAILED'), 1000))
app.get('/start', asyncHandler(async (_req, res) => {
// I want to be able to initiate the process and send back
// confirmation that the process has been started. I want the
// client to be able forget about this request.
res.json('ok...started process')
// Then we start to run the heavy IO process. Without the "await" this could
// lead to unhandled promise rejection.
// If this fails, the rejected promise will flow to express default
// error handling which is I think "finalhandler" by default.
// Because the headers as sent (res.headersSent === true) the error
// handler will log the error and destroy the socket connection.
// If this succeeds, the server will probably close the socket connection as well
// internally.
// Up until this point the socket has been open (or half-open?) so is this a problem?
// Does it mean that the client has been "up-keeping" this socket connection
// somehow or has/can it have been timed out before this succeeds or fails.
await heavyIO()
console.log(`FINISHED I/O at ${new Date().toISOString()}! Exiting handler...`)
}))
app.listen(8080)
解决方案
推荐阅读
- php - PHP 使用 foreach 遍历 JSON
- javascript - 根据匹配的键/值属性过滤对象数组?
- mongodb - Grails 3 使用 _id 和 id 保存 mongoDB 文档
- sql-server - 为什么日志传送数据库在链接服务器上不可见?
- python - 使用 ifelse 条件创建新列(python)
- java - 未知配置格式:hocon(支持的格式有:[json, raw, properties]
- c# - ASP.NET Core Web API 自动 JSON 参数反序列化不起作用
- python - JSON 模式语法检查器
- java - 正则表达式性能 java vs c++11
- sql - PostgreSQL:计数查询需要太多时间