迁移至Supabase后NextJS工具函数随机调用失败求助
问题描述
我基于NextJS、Prisma、Supabase(近期从PlanetScale迁移)及Clerk认证开发了Web应用。启动应用时,获取用户/企业数据的工具函数会调用失败,提示无法读取返回数据的某个属性,但刷新页面后服务器又能成功获取数据。已为函数添加try/catch块,Supabase模型也配置了RLS规则,使用PlanetScale时未出现该问题,不确定是网络速度不佳、工具函数写法有误还是Supabase配置不当导致。
示例工具函数
获取用户信息函数
export const getUserByClerkID = async () => { const { userId } = await auth() //console.log('CLERK USER ID ', userId) try { const user = await prisma.user.findUnique({ where: { clerkId: userId, }, }) return user } catch (error) { console.error('Error fetching user by clerk ID', error) } }
获取企业数据函数
export const fetchOrgData = async () => { const user = await getUserByClerkID() console.log('USER WHILE FETCHING ORG DATA', user) try { const orgData = await prisma.company.findFirst({ where: { employees: { some: { clerkId: user.clerkId, }, }, }, include: { employees: true, teams: true, savedCandidates: true, messageThreads: true, }, }) return orgData } catch (error) { console.error('Error fetching org data', error) } }
排查思路与解决方案
1. 认证时机校验
auth()在NextJS组件/路由初始化阶段可能未完成认证,导致userId为undefined,进而getUserByClerkID返回undefined,后续fetchOrgData访问user.clerkId直接报错。
- 修复方案:在函数中增加空值判断,避免无效调用:
修改getUserByClerkID:
修改export const getUserByClerkID = async () => { const { userId } = await auth() if (!userId) { console.warn('未获取到Clerk用户ID') return null } try { const user = await prisma.user.findUnique({ where: { clerkId: userId, }, }) return user } catch (error) { console.error('通过Clerk ID获取用户失败', error) return null } }fetchOrgData:export const fetchOrgData = async () => { const user = await getUserByClerkID() if (!user) { console.warn('无有效用户,无法获取企业数据') return null } try { const orgData = await prisma.company.findFirst({ where: { employees: { some: { clerkId: user.clerkId, }, }, }, include: { employees: true, teams: true, savedCandidates: true, messageThreads: true, }, }) return orgData } catch (error) { console.error('获取企业数据失败', error) return null } }
2. Supabase RLS规则验证
迁移后RLS规则可能存在逻辑漏洞,或者Prisma连接Supabase时未正确传递认证上下文,导致首次请求被RLS拦截返回空数据。
- 检查RLS规则:确保
user和company表的规则允许当前认证用户访问对应数据。例如user表规则应限定仅能访问自身数据:CREATE POLICY "用户仅能查看自身数据" ON public.user FOR SELECT USING (auth.uid() = id); - 确认Prisma连接时是否注入Clerk认证信息:在NextJS Server Component中,需保证
auth()返回的用户信息能被Supabase的RLS识别,可在Prisma客户端初始化时传递Supabase JWT。
3. 异步数据加载优化
若在客户端组件直接调用这些函数,首次渲染时异步数据未返回就尝试访问属性会报错,刷新后数据已缓存则正常。
- 修复方案:在Server Component中预取数据,或使用
useSWR/react-query等缓存库处理异步请求,确保数据加载完成后再渲染相关内容。
4. 网络连接重试配置
首次启动时Supabase连接初始化慢可能导致请求超时失败,刷新后连接已建立则请求成功。
- 修复方案:给Prisma请求添加重试逻辑,或在Prisma配置中设置连接超时与重试次数:
在prisma/schema.prisma中修改:datasource db { provider = "postgresql" url = env("DATABASE_URL") shadowDatabaseUrl = env("SHADOW_DATABASE_URL") connectTimeout = 10 // 连接超时时间(秒) poolTimeout = 10 // 池超时时间(秒) }
内容的提问来源于stack exchange,提问作者Morgan Pierson
相关产品推荐
相关产品推荐

