如何在Zod的superRefine中设置异步验证?解决同步解析报错
解决Zod异步验证报错:Async refinement encountered during synchronous parse operation
报错原因
你的superRefine里用了异步逻辑(await prisma.user.findUnique),但调用Schema验证时用了同步的.parse()方法——Zod不允许在同步解析流程里执行异步校验,必须用对应的异步解析方法。
解决方案
1. 替换解析方法
把所有调用registerSchema.parse(xxx)的地方,改成await registerSchema.parseAsync(xxx)。因为异步验证返回Promise,必须用await处理结果。
2. 优化Schema逻辑(可选但推荐)
把同步验证(比如密码和确认密码匹配)和异步验证(数据库查重)拆分,同步逻辑提前执行能提升效率,同时修正代码里的冗余参数:
- 给
confirm字段单独加同步验证,确保和password一致 - 删掉
superRefine参数里多余的username(你的Schema没定义这个字段,会导致解构错误) - 异步部分只保留数据库查询的逻辑
修改后的完整代码
import { prisma } from '../../../helper/prisma' import { z } from 'zod' export const registerSchema = z.object({ email: z.string().min(1, { message: "Email field is required" }).trim().email({ message: "Email is invalid" }), password: z.string().min(7, { message: "Password must have more than 6 characters" }).trim(), confirm: z.string().trim().min(1, { message: "Confirm password field is required" }) }) // 同步验证密码一致性 .refine((data) => data.password === data.confirm, { message: "Passwords do not match", path: ["confirm"] }) // 异步验证邮箱是否已存在 .superRefine(async ({ email }, ctx) => { const emailExists = await prisma.user.findUnique({ where: { email } }) if (emailExists) { ctx.addIssue({ code: "custom", message: "The email already exists", path: ["email"] }) } })
调用示例
// 必须在异步函数中调用 async function handleRegister(formData) { try { const validatedData = await registerSchema.parseAsync(formData) // 执行后续注册逻辑 } catch (error) { // 处理验证错误 console.error(error.issues) } }
内容的提问来源于stack exchange,提问作者Emanuek
相关产品推荐
相关产品推荐

