74 lines
1.9 KiB
Markdown
74 lines
1.9 KiB
Markdown
---
|
|
title: Use after() for Non-Blocking Operations
|
|
impact: MEDIUM
|
|
impactDescription: faster response times
|
|
tags: server, async, logging, analytics, side-effects
|
|
---
|
|
|
|
## 使用 after() 实现非阻塞操作
|
|
|
|
使用 Next.js 的 `after()` 来安排在响应发送之后执行的工作。这样可以防止日志记录、分析及其他副作用阻塞响应。
|
|
|
|
**错误做法(阻塞响应):**
|
|
|
|
```tsx
|
|
import { logUserAction } from '@/app/utils'
|
|
|
|
export async function POST(request: Request) {
|
|
// 执行变更操作
|
|
await updateDatabase(request)
|
|
|
|
// 日志记录阻塞了响应
|
|
const userAgent = request.headers.get('user-agent') || 'unknown'
|
|
await logUserAction({ userAgent })
|
|
|
|
return new Response(JSON.stringify({ status: 'success' }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
}
|
|
```
|
|
|
|
**正确做法(非阻塞):**
|
|
|
|
```tsx
|
|
import { after } from 'next/server'
|
|
import { headers, cookies } from 'next/headers'
|
|
import { logUserAction } from '@/app/utils'
|
|
|
|
export async function POST(request: Request) {
|
|
// 执行变更操作
|
|
await updateDatabase(request)
|
|
|
|
// 在响应发送之后进行日志记录
|
|
after(async () => {
|
|
const userAgent = (await headers()).get('user-agent') || 'unknown'
|
|
const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous'
|
|
|
|
logUserAction({ sessionCookie, userAgent })
|
|
})
|
|
|
|
return new Response(JSON.stringify({ status: 'success' }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
}
|
|
```
|
|
|
|
响应会立即发送,同时日志记录在后台进行。
|
|
|
|
**常见使用场景:**
|
|
|
|
- 分析跟踪
|
|
- 审计日志
|
|
- 发送通知
|
|
- 缓存失效
|
|
- 清理任务
|
|
|
|
**重要说明:**
|
|
|
|
- `after()` 即使响应失败或重定向也会执行
|
|
- 适用于 Server Actions、Route Handlers 和 Server Components
|
|
|
|
参考文档:[https://nextjs.org/docs/app/api-reference/functions/after](https://nextjs.org/docs/app/api-reference/functions/after)
|