var Schema = require('async-validator');
var descriptor = {
name: {type: "string", required: true}
}
var validator = new Schema(descriptor);
validator.validate({name: "muji"}, (errors, fields) => {
if(errors) {
// validation failed, errors is an array of all errors
// fields is an object keyed by field name with an array of
// errors per field
return handleErrors(errors, fields);
}
// validation passed
});
缘由
在使用antd时,其表单验证使用一个单独的npm包async-validator实现,其使用可以参考async-validator使用。但一直很好奇:
源码分析
1. 使用概述
首先看一个
async-validator
的使用例子:核心就是两步操作:
2. 纵观全局
结合上述示例,简化一下源码:
主要API就这两个:一个
define
用来定义规则,一个validate
用于根据规则校验来检测数据是否满足要求。3.
define
实现具体源码:
这个api就是把定义的验证规则,整理一下然后存储到
this.rules
中,以备后用。 如上示例的rules是:执行之后,将其保存到rules中:
4.
validate
实现这个API就比较有意思了,有意思的意思就是这里面的代码真的是简直了,各种callback,差些可以头冒金星。大致看看源码缩略版本:
来来来,不用怕,来分析分析,其流程就是:
asyncMap
函数,提供两个回调函数,一个是实际验证数据使用,暂时给其命名为asyncValidateMethod
;一个处理全部校验结果,可以称之为validateFinished
asyncMap
函数中对具体字段调用asyncParallelArray
进行校验,然后收集字段的所有错误信息,收集完之后,调用validateFinished
asyncParallelArray
函数针对具体字段的单个规则调用asyncValidateMethod
对其进行验证,同时这个函数里面会针对具体字段收集其错误信息,因为一个字段可以对应多个验证规则,所以可能会有多条错误信息,然后完之后,汇总到asyncMap
中。validate
的回调函数。答疑解惑
1. 如何实现异步校验的?
看完源码之后,除了回调比较多之外,好像没有在哪发现使用了异步。为了验证这个想法, 首先我们构造一段代码:
如果验证是异步的话,打印结果应该是:
然而实际结果是:
所以这个其实不是异步校验,完全就是一个同步进行的过程。
2. 如何支持那么多中校验规则?
看看目录情况就比较好理解了: 有一个
rule
和一个validator
目录,validator
目录放的就是支持的所有的验证规则,实际校验行为rule
目录下的文件完成的。 例如最简单的必填校验({require: true}),首先会调用validator/required.js
中方法:这个里面又会使用到
rule/required.js
中的方法:待探索