angular异步验证防抖踩坑实录


Posted in Javascript onDecember 01, 2019

前言

本周的一个需求是在一个异步验证上加上防抖,防抖,以前也接触过,依稀记得不难,就没再去看angluar的官方文档,直接就开始google写了,然后……一不小心就掉坑里了。

突然没了效果的验证功能

在网上一番查询以后,选了一个最简单,最符合的实现

angular异步验证防抖踩坑实录

一番修改以后我的代码成了下面这样

public oldPasswordValidator(): AsyncValidatorFn {
  return (ctrl: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
  rerutn ctrl.valueChanges.pipe(
    debounceTime(2000),
    distinctUntilChanged(),
    switchMap(value => this.checkPasswordIsRight(value)),
    map((isRight: boolean) => (isRight ? null : {passwordError: true})),
    catchError(() => null));
  };

但是验证器并没有效果,在c层获取到的始终是null,而在方法中打印结果,却可以发现,能够产生正确的结果

angular异步验证防抖踩坑实录

但是获取到的相关错误一直是没有,更让我感到惊讶的是表单的valid和invalid竟然同时处在了false,他们不是应该互斥吗?不是反义词吗?

angular异步验证防抖踩坑实录

FormControl的status

首先还是解决valid与invalid的疑惑吧,查询官方文档。

FormControl的status继承自AbstractControl

AbstractControl是 FormControl、FormGroup 和 FormArray 的基类。它提供了一些所有控件和控件组共有的行为,比如运行验证器、计算状态和重置状态。 它还定义了一些所有子类共享的属性,如 value、valid 和 dirty。不允许直接实例化它。

找到valid

angular异步验证防抖踩坑实录

至此,这个疑问解决了,互斥的并不仅仅是valid和invalid,

还有一个检查进行状态:pending和禁止disable,验证一下,果然此时的状态是在pending

angular异步验证防抖踩坑实录

为何会一直在pending状态?

接着查看表单验证的官方文档

自定义异步验证器和同步验证器很像,只是它们必须返回一个稍后会输出 null 或“验证错误对象”的承诺(Promise)或可观察对象,如果是可观察对象,那么它必须在某个时间点被完成(complete),那时候这个表单就会使用它输出的最后一个值作为验证结果。(译注:HTTP 服务是自动完成的,但是某些自定义的可观察对象可能需要手动调用 complete 方法)
返回的可观察对象必须是有限的,也就是说,它必须在某个时间点结束(complete)。要把无尽的可观察对象转换成有限的,可以使用 first、last、take 或 takeUntil 等过滤型管道对其进行处理。

结果很明显了,上面的观察者对象是通过valueChangs产生的, 被人订阅后,并不会主动的调用complete()方法,而会不停的发布新值。下面的例子可以看出来

angular异步验证防抖踩坑实录

给他加个first()让他只返回第一个结果,果然好使了:

angular异步验证防抖踩坑实录

first(predicate: function(value: T, index: number, source: Observable<T>): boolean, resultSelector:function(value: T, index: number): R, defaultValue: R): Observable<T | R>
只发出由源 Observable 所发出的值中第一个(或第一个满足条件的值)。

如果你足够细心

angular异步验证防抖踩坑实录

看的太不仔细了,到解决这个问题之前,一直都没发现……

一个更简单的实现方式

验证的防抖功能实际上并不需要通过上面的方式实现,尽管上面也并不困难。

最简单的防抖方式,在官方文档已经提供了:

默认情况下,每当表单值变化之后,都会执行所有验证器。对于同步验证器,没有什么会显著影响应用性能的地方。不过,异步验证器通常会执行某种 HTTP 请求来对控件进行验证。如果在每次按键之后都发出 HTTP 请求会给后端 API 带来沉重的负担,应该尽量避免。

我们可以把updateOn属性从change(默认值)改成submit或blur来推迟表单验证的更新时机。

/**
  * 初始化表单
  */
 initForm() {
  this.modifyPasswordForm = this.fb.group({
    oldPassword: [null, [Validators.required], [this.userService.oldPasswordValidator()]],
    newPassword: [null, Validators.required],
    confirmNewPassword: [null, Validators.required]

    // updateOn 作用是在什么时候更新表单数据
    // https://angular.cn/guide/form-validation#note-on-performance
   }, {updateOn: 'blur'},
  );
 }

想了解更多updateOn的内容,可查看这篇文章。

总结

这次的问题可以完全说出在了看文档不仔细,神奇的是看了几遍那个StackOverflow上的回答都没发现他比我多了一个first(),虽然因此浪费了不少的时间,但收获也是巨大的,这波不亏。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js 变量类型转换常用函数与代码[比较全]
Dec 01 Javascript
JS替换文本域内的回车示例
Feb 18 Javascript
js校验表单后提交表单的三种方法总结
Feb 28 Javascript
谷歌地图打不开的解决办法
Aug 07 Javascript
jQuery Ajax中的事件详细介绍
Apr 16 Javascript
jQuery插件制作的实例教程
May 16 Javascript
js改变style样式和css样式的简单实例
Jun 28 Javascript
JS实现滑动门效果的方法详解
Dec 19 Javascript
Angular.js之作用域scope'@','=','&amp;'实例详解
Feb 28 Javascript
vuejs事件中心管理组件间的通信详解
Aug 09 Javascript
vue动态配置模板 'component is'代码
Jul 04 Javascript
JavaScript 判断数据类型的4种方法
Sep 11 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
Dec 01 #Javascript
Node.js中console.log()输出彩色字体的方法示例
Dec 01 #Javascript
Node.js控制台彩色输出的方法与原理实例详解
Dec 01 #Javascript
vue多个元素的样式选择器问题
Nov 29 #Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
Nov 29 #Javascript
vue 组件开发原理与实现方法详解
Nov 29 #Javascript
vue ajax 拦截原理与实现方法示例
Nov 29 #Javascript
You might like
PHP 7安装使用体验之性能大提升,兼容性强,扩展支持不够(升级PHP要谨慎)
2017/07/27 PHP
JS中简单的实现像C#中using功能(有源码下载)
2007/01/09 Javascript
Jquery+WebService 校验账号是否已被注册的代码
2010/07/12 Javascript
javascript 判断中文字符长度的函数代码
2012/08/27 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
js实现文本框选中的方法
2015/05/26 Javascript
JavaScript驾驭网页-获取网页元素
2016/03/24 Javascript
jQuery-ui插件sortable实现自由拖动排序
2018/12/01 jQuery
解决vue cli使用typescript后打包巨慢的问题
2019/09/30 Javascript
Javascript 类型转换、封闭函数及常见内置对象操作示例
2019/11/15 Javascript
vue倒计时刷新页面不会从头开始的解决方法
2020/03/03 Javascript
[04:04]显微镜下的DOTA2第六期——电影级别的华丽团战
2014/06/20 DOTA
Python 代码性能优化技巧分享
2012/08/07 Python
基于Python实现的扫雷游戏实例代码
2014/08/01 Python
Python中处理字符串之islower()方法的使用简介
2015/05/19 Python
简介Django中内置的一些中间件
2015/07/24 Python
Python实现截屏的函数
2015/07/25 Python
批量获取及验证HTTP代理的Python脚本
2017/04/23 Python
基于python3 类的属性、方法、封装、继承实例讲解
2017/09/19 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
2017/11/09 Python
安装Pycharm2019以及配置anconda教程的方法步骤
2019/11/11 Python
python批量修改xml属性的实现方式
2020/03/05 Python
python求前n个阶乘的和实例
2020/04/02 Python
整理HTML5的一些新特性与Canvas的常用属性
2016/01/29 HTML / CSS
澳大利亚连衣裙和女装在线:Esther
2017/11/11 全球购物
Qoo10台湾站:亚洲领先的在线市场
2018/05/15 全球购物
Quiksilver荷兰官方网站:冲浪和滑雪板
2019/11/16 全球购物
神路信息Java面试题目
2013/03/31 面试题
设计模式的基本要素是什么
2014/04/21 面试题
哈弗商学院毕业生求职信
2014/02/26 职场文书
有限公司股东合作协议书
2014/10/29 职场文书
管理失职检讨书
2015/05/05 职场文书
退休欢送会主持词
2015/07/01 职场文书
六一儿童节致辞稿(3篇)
2019/07/11 职场文书
分析Java中Map的遍历性能问题
2021/06/26 Java/Android
唤醒紫霞仙子,携手再游三界!大话手游X《大话西游》电影合作专属剧情任务
2022/04/03 其他游戏