Next.js API函数单次调用多次执行,首次请求无POST数据问题排查
问题分析与解决方案
核心问题
- 首次调用无POST数据:SWR默认使用GET请求发起API调用,而你的服务端代码从
req.body(仅POST请求携带)获取submissionId,首次GET请求自然没有body数据,触发"contact does not exist"错误。 - 后端函数多次执行:Next.js动态路由的
router.query在页面初始加载时可能为空(参数需要时间解析),导致SWR先发起一次无submissionId的请求,等参数加载完成后又发起第二次有效请求,所以后端函数执行两次。
修复方案
方案1:改用GET传递参数(更符合当前SWR的使用习惯)
调整服务端从req.query获取参数,同时确保客户端在submissionId存在时才发起请求:
客户端代码修改:
export default function Customer () { const router = useRouter() const { id: submissionId } = router.query // 只有submissionId存在时才发起请求 const { data: customer, error } = useSWR(submissionId ? ['/api/jotform/get-client', submissionId] : null, fetcher) ... } // 调整fetcher,把submissionId作为查询参数传递 const fetcher = async (url, submissionId) => { const res = await fetch(`${url}?submissionId=${submissionId}`) return res.json() }
服务端代码修改:
export default async function handler (req, res) { try { const customers = await axios.get(`https://api.jotform.com/form/${jotformAPI.form_id}/submissions?apiKey=${jotformAPI.key}`) // 从req.query获取submissionId,而非req.body const { submissionId } = req.query if (!submissionId) { return res.status(400).json({ error: 'Missing submissionId' }) } const customer = customers.data.content.find(client => client.id === submissionId) if (!customer) throw new Error('contact does not exist') // 后续逻辑... res.status(200).json(customer) } catch (err) { res.status(404).json({ error: err.message }) } }
方案2:改用POST请求(如果业务需要POST)
修改SWR的fetcher发起POST请求,同样确保submissionId存在才触发请求:
客户端代码修改:
export default function Customer () { const router = useRouter() const { id: submissionId } = router.query const { data: customer, error } = useSWR(submissionId ? ['/api/jotform/get-client', submissionId] : null, async (url, id) => { const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ submissionId: id }) }) return res.json() }) ... }
服务端代码补充:
先判断请求方法,确保仅处理POST请求:
export default async function handler (req, res) { // 只接受POST请求 if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }) } try { const customers = await axios.get(`https://api.jotform.com/form/${jotformAPI.form_id}/submissions?apiKey=${jotformAPI.key}`) const { submissionId } = req.body if (!submissionId) { return res.status(400).json({ error: 'Missing submissionId' }) } const customer = customers.data.content.find(client => client.id === submissionId) if (!customer) throw new Error('contact does not exist') // 后续逻辑... res.status(200).json(customer) } catch (err) { res.status(404).json({ error: err.message }) } }
额外优化建议
- 可以在服务端缓存Jotform API的响应,避免每次请求都调用外部API,减少重复请求和延迟。
- 开发模式下Next.js会有热重载,可能导致API路由重复执行,生产环境会缓解这个问题。
内容的提问来源于stack exchange,提问作者ilyo
相关产品推荐
相关产品推荐

