概览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重复提交被吞并;用户反馈清晰、无重复扣款/记录

发表评论 取消回复