You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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状态,也会导致前端状态异常。

修复步骤

  1. 修正Route Handler的返回值解构
    将Supabase操作的解构代码修改为:
const { data: recipe, error } = await supabase.from("Recipes").insert(data);

通过data: recipe重命名返回的data字段,避免解构错误。

  1. 完善Route Handler的错误信息返回
    在catch块中返回具体错误信息,确保函数及时终止并返回响应:
catch (error) {
    return NextResponse.json({error: error.message || "error in try catch", status: 500})
}
  1. 修复客户端的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 08:27:08