概览Server Actions 在弱网与并发场景可能出现重复提交。通过幂等键与请求指纹可消除重复执行,并以退避策略改善重试体验。后端幂等键app/actions.ts'use server'

const seen = new Map<string, number>()

export async function pay(data: FormData) {

const key = String(data.get('idempotency_key') || '')

if (!key) return { ok: false, message: '缺少幂等键' }

if (seen.has(key)) return { ok: true, message: '已处理' }

await new Promise((r) => setTimeout(r, 500))

seen.set(key, Date.now())

return { ok: true, message: '支付成功' }

}

客户端提交'use client'

import { useActionState } from 'react'

import { pay } from '../actions'

export default function PayForm() {

const [state, action, pending] = useActionState(async (_prev, formData) => {

'use server'

return pay(formData)

}, { ok: false, message: '' })

function genKey() {

return crypto.randomUUID()

}

return (

<form action={action} aria-describedby="status">

<input name="amount" type="number" required />

<input name="idempotency_key" type="hidden" value={genKey()} />

<button disabled={pending}>{pending ? '处理中…' : '支付'}</button>

<p id="status" role="status">{state.message || '请输入金额'}</p>

</form>

)

}

去重与退避// 对可能的重复提交进行退避重试

async function retry<T>(fn: () => Promise<T>, tries = 3) {

let i = 0

while (i < tries) {

try { return await fn() } catch (e) { await new Promise(r => setTimeout(r, 300 * (i + 1))) }

i++

}

throw new Error('重试失败')

}

治理要点幂等键在后端存储(KV/DB),确保跨实例一致;设置过期与清理。将去重与退避封装在 Server Actions 与客户端提交路径中,避免状态撕裂。在成功后触发标签/路径失效,保持数据一致性。验证与指标Next.js:15.0+;Node.js:20.x重复提交被吞并;用户反馈清晰、无重复扣款/记录

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部