Next.js路由处理器执行完毕后浏览器加载图标持续旋转
问题:提交表单后浏览器加载图标持续旋转,部署后Serverless函数超时
客户端提交代码
客户端组件的表单提交函数如下:
const handleSubmit = async () => { setLoading(true); try { const res = await fetch("/api/saveRecipe", { method: "POST", // or 'PUT' headers: { "Content-Type": "application/json", }, body: JSON.stringify({ title: title, time: time, time_unit: timeUnit, serves: serves, ingredients: ingredients, instructions: instructions, }), }); const data = await res.json(); if (data.status == 200 && res.ok) { router.push("/"); } else { console.log(data.error); setLoading(false); setError(true); } } catch (e) { console.log(e.message || e.description); } };
提交后调用/api/saveRecipe接口,成功则重定向至首页。
Route Handler代码
对应的路由处理器实现:
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; import { cookies } from "next/headers"; import { NextResponse } from "next/server"; export const dynamic = "force-dynamic"; export async function POST(req) { const supabase = createRouteHandlerClient({ cookies }); try { const data = await req.json(); const { recipe, error } = await supabase.from("Recipes").insert(data); if (error) { return NextResponse.json({error: "error from supabase", status: 500}) } } catch (error) { return NextResponse.json({error: "error in try catch", status: 500}) } return NextResponse.json({status: 200}) }
问题现象
- 点击提交后,浏览器标签页的加载图标持续旋转,即使已经收到接口响应并重定向到首页
- 部署后出现
this Serverless function timed out错误,网站无法正常使用
问题分析与修复
核心问题
Supabase插入操作的返回值解构错误:supabase.from("Recipes").insert(data)返回的对象包含data和error字段,而非代码中的recipe,这会导致解构失败进入catch块,未正确终止函数的情况下可能引发超时。另外客户端代码的成功分支未重置loading状态,也会导致前端状态异常。
修复步骤
- 修正Route Handler的返回值解构
将Supabase操作的解构代码修改为:
const { data: recipe, error } = await supabase.from("Recipes").insert(data);
通过data: recipe重命名返回的data字段,避免解构错误。
- 完善Route Handler的错误信息返回
在catch块中返回具体错误信息,确保函数及时终止并返回响应:
catch (error) { return NextResponse.json({error: error.message || "error in try catch", status: 500}) }
- 修复客户端的loading状态
在成功分支和异常分支都添加setLoading(false),确保前端状态正确重置:
if (data.status == 200 && res.ok) { setLoading(false); router.push("/"); } else { console.log(data.error); setLoading(false); setError(true); } // ... catch (e) { console.log(e.message || e.description); setLoading(false); setError(true); }
修改后的完整代码
客户端提交函数
const handleSubmit = async () => { setLoading(true); try { const res = await fetch("/api/saveRecipe", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ title: title, time: time, time_unit: timeUnit, serves: serves, ingredients: ingredients, instructions: instructions, }), }); const data = await res.json(); if (data.status == 200 && res.ok) { setLoading(false); router.push("/"); } else { console.log(data.error); setLoading(false); setError(true); } } catch (e) { console.log(e.message || e.description); setLoading(false); setError(true); } };
Route Handler
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; import { cookies } from "next/headers"; import { NextResponse } from "next/server"; export const dynamic = "force-dynamic"; export async function POST(req) { const supabase = createRouteHandlerClient({ cookies }); try { const data = await req.json(); const { data: recipe, error } = await supabase.from("Recipes").insert(data); if (error) { return NextResponse.json({error: "error from supabase", status: 500}) } } catch (error) { return NextResponse.json({error: error.message || "error in try catch", status: 500}) } return NextResponse.json({status: 200}) }
内容的提问来源于stack exchange,提问作者Saif eldeen Adel
相关产品推荐
相关产品推荐

