Timeout 中间件
Timeout 中间件可帮助你轻松管理请求超时,为请求设定最大执行时长,并在超时后返回自定义错误响应。
导入
ts
import { Hono } from 'hono'
import { timeout } from 'hono/timeout'用法
以下示例展示了默认配置与自定义配置:
默认配置:
ts
const app = new Hono()
// 为 /api 路径设置 5 秒超时
app.use('/api', timeout(5000))
// 路由处理
app.get('/api/data', async (c) => {
// 处理逻辑
return c.json({ data: 'Your data here' })
})自定义配置:
ts
import { HTTPException } from 'hono/http-exception'
// 自定义异常工厂函数
const customTimeoutException = (context) =>
new HTTPException(408, {
message: `Request timeout after waiting ${context.req.headers.get(
'Duration'
)} seconds. Please try again later.`,
})
// 若仅需固定消息
// const customTimeoutException = new HTTPException(408, {
// message: 'Operation timed out. Please try again later.'
// })
// 为 /api/long-process 设置 1 分钟超时并使用自定义异常
app.use('/api/long-process', timeout(60000, customTimeoutException))
app.get('/api/long-process', async (c) => {
// 模拟耗时操作
await new Promise((resolve) => setTimeout(resolve, 61000))
return c.json({ data: 'This usually takes longer' })
})注意事项
- 超时时长使用毫秒,超时后中间件会拒绝 Promise,并可能抛出异常。
- Timeout 中间件无法直接用于流式响应。此类场景可配合
stream.close与setTimeout一同使用。
ts
app.get('/sse', async (c) => {
let id = 0
let running = true
let timer: number | undefined
return streamSSE(c, async (stream) => {
timer = setTimeout(() => {
console.log('Stream timeout reached, closing stream')
stream.close()
}, 3000) as unknown as number
stream.onAbort(async () => {
console.log('Client closed connection')
running = false
clearTimeout(timer)
})
while (running) {
const message = `It is ${new Date().toISOString()}`
await stream.writeSSE({
data: message,
event: 'time-update',
id: String(id++),
})
await stream.sleep(1000)
}
})
})中间件冲突
当使用其他错误处理或与时间相关的中间件时,请注意调用顺序,避免影响 Timeout 中间件的行为。