Joi自定义邮箱唯一性验证无法返回错误消息问题
问题解决:Joi异步自定义验证不返回错误的原因及修复
核心问题
你的自定义验证函数是异步(async)的,但如果使用Joi的同步验证方法validate(),它会直接忽略异步操作的结果,导致即使检测到重复邮箱,错误也无法被捕获。另外,使用any.invalid错误码不够明确,也会影响错误信息的可读性。
修复步骤
1. 使用Joi异步验证方法validateAsync()
替换同步的validate()为异步的validateAsync(),并通过try/catch捕获错误:
// 验证数据的代码示例 async function validateVideoData(data) { try { const validatedData = await videosSchema.validateAsync(data); return { success: true, data: validatedData }; } catch (err) { return { success: false, error: err.details[0].message }; } }
2. 优化自定义验证函数的错误返回
使用更明确的自定义错误码,让错误信息更清晰:
const isUniqueEmail = async (value, helpers) => { const user = await User.query().where("email", value).first(); if (user) { // 返回自定义错误码 return helpers.error('email.alreadyExists'); } return value; };
3. 更新Schema配置
为邮箱字段添加错误消息映射,同时推荐使用.external()替代.custom()(Joi官方更推荐用.external()处理异步验证逻辑):
const videosSchema = Joi.object({ channel_id: Joi.number().required().label("Channel Id"), email: Joi.string() .required() .external(isUniqueEmail) .messages({ 'email.alreadyExists': '该邮箱已被注册,请更换其他邮箱', 'string.empty': '邮箱不能为空', 'any.required': '邮箱为必填项' }), title: Joi.string().required().min(5).max(50), });
为什么之前的代码不生效?
- Joi的
validate()是同步方法,不会等待异步自定义函数的Promise完成,所以无法捕获到异步抛出的错误。 any.invalid是通用错误码,可能被Joi的其他规则覆盖,导致错误信息无法正确返回。
内容的提问来源于stack exchange,提问作者Abdulrahman
相关产品推荐
相关产品推荐

