跳到主要内容

after

after 允许你安排工作在响应(或预渲染)完成后执行。这对于不应该阻塞响应的任务和其他副作用很有用,例如日志记录和分析。

它可以在 服务端组件(包括 generateMetadata)、服务器操作路由处理器中间件 中使用。

该函数接受一个回调函数,该回调函数将在响应(或预渲染)完成后执行:

app/layout.tsx
import { after } from 'next/server'
// 自定义日志记录函数
import { log } from '@/app/utils'

export default function Layout({ children }: { children: React.ReactNode }) {
after(() => {
// 在布局渲染并发送给用户后执行
log()
})
return <>{children}</>
}

提示after 不是 动态 API,调用它不会导致路由变为动态。如果在静态页面中使用,回调将在构建时或页面重新验证时执行。

参考

参数

  • 一个回调函数,将在响应(或预渲染)完成后执行。

持续时间

after 将运行平台默认或配置的路由最大持续时间。如果你的平台支持,你可以使用 maxDuration 路由段配置来配置超时限制。

提示

  • 即使响应没有成功完成,after 也会被执行。包括抛出错误或调用 notFoundredirect 时。
  • 你可以使用 React cache 来去重 after 内部调用的函数。
  • after 可以嵌套在其他 after 调用中,例如,你可以创建包装 after 调用的实用函数来添加额外功能。

示例

与请求 API 一起使用

你可以在 服务器操作路由处理器 中的 after 内部使用请求 API,如 cookiesheaders。这对于在变更后记录用户活动很有用。例如:

app/api/route.ts
import { after } from 'next/server'
import { cookies, headers } from 'next/headers'
import { logUserAction } from '@/app/utils'

export async function POST(request: 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 内部使用这些请求 API。这是因为 Next.js 需要知道树的哪一部分访问请求 API 以支持 部分预渲染,但 after 在 React 的渲染生命周期之后运行。

平台支持

部署选项支持
Node.js 服务器
Docker 容器
静态导出
适配器平台特定

了解在自托管 Next.js 时如何 配置 after

参考:为无服务器平台支持 after

在无服务器上下文中使用 after 需要等待异步任务在响应发送后完成。在 Next.js 和 Vercel 中,这是通过使用称为 waitUntil(promise) 的原始方法实现的,它扩展无服务器调用的生命周期,直到传递给 waitUntil 的所有 Promise 都已解决。

如果你希望用户能够运行 after,你将必须提供 waitUntil 的实现,其行为类似。

当调用 after 时,Next.js 将像这样访问 waitUntil

const RequestContext = globalThis[Symbol.for('@next/request-context')]
const contextValue = RequestContext?.get()
const waitUntil = contextValue?.waitUntil

这意味着 globalThis[Symbol.for('@next/request-context')] 应该包含一个像这样的对象:

type NextRequestContext = {
get(): NextRequestContextValue | undefined
}

type NextRequestContextValue = {
waitUntil?: (promise: Promise<any>) => void
}

以下是实现的示例。

import { AsyncLocalStorage } from 'node:async_hooks'

const RequestContextStorage = new AsyncLocalStorage<NextRequestContextValue>()

// 定义并注入 next.js 将使用的访问器
const RequestContext: NextRequestContext = {
get() {
return RequestContextStorage.getStore()
},
}
globalThis[Symbol.for('@next/request-context')] = RequestContext

const handler = (req, res) => {
const contextValue = { waitUntil: YOUR_WAITUNTIL }
// 提供值
return RequestContextStorage.run(contextValue, () => nextJsHandler(req, res))
}

版本历史

版本历史描述
v15.1.0after 变为稳定版本。
v15.0.0-rc引入了 unstable_after