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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 09:42:38