一、相关接口
就像同步验证器有 ValidatorFn 和 Validator 接口一样,异步验证器也有自己的对应接口:AsyncValidatorFn 和 AsyncValidator。
接口介绍及注意:
- 它们必须返回Promise或可Observable对象
- 返回的可观察对象必须是有限的,也就是说,它必须在某个时间点结束(complete)。要把无尽的可观察对象转换成有限的,可以使用 first、last、take 或 takeUntil 等过滤型管道对其进行处理。
- 异步验证总是会在同步验证之后执行,并且只有当同步验证成功了之后才会执行。如果更基本的验证方法已经失败了,那么这能让表单避免进行可能会很昂贵的异步验证过程,比如 HTTP 请求。
- 在异步验证器开始之后,表单控件会进入 pending 状态。(此时表单的valid和invalid状态均为false)
二、异步验证消抖
性能上的注意事项
默认情况下,每当表单值变化之后,都会执行所有验证器。对于同步验证器,没有什么会显著影响应用性能的地方。不过,异步验证器通常需要向后端发送请求(比如查询某个输入值是否在数据库已存在从而进行查重验证),因此我们需要消抖。
简单方法
把 updateOn 属性从 change(默认值)改成 submit 或 blur,进而在表单控件blur时才进行验证
this.validateForm = this.fb.group({
userName: ['', [Validators.required]],
email: ['', [Validators.email, Validators.required]],
},{updateOn:'blur'});
但是在用户输入完长长的一段内容再blur之后才给他看验证结果,如果验证成功了还好,验证失败的话会影响交互体验
异步验证消抖
话不多说,先上代码
emailAsyncValidator():AsyncValidatorFn{
//返回一个AsyncValidatorFn函数
return (control:FormControl):Observable<ValidationErrors | null>=>{
//返回一个Observable对象(注意几个rxjs操作符的处理)
return control.valueChanges.pipe(debounceTime(300)).pipe(first()).pipe(switchMap(res=>
Observable.create((observer: Observer<ValidationErrors>)=>{
this.apiService.post().subscribe(res=>{
if(res.json().data.length>0){
observer.next({ error: true, duplicated: true });
}else{
observer.next(null);
}
observer.complete()
})
})
))
}
}