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 相关文章推荐
JavaScript的面向对象(二)
Nov 09 Javascript
web css实现整站样式互相切换
Oct 29 Javascript
jQuery学习笔记之Ajax用法实例详解
Dec 01 Javascript
AngularJS进行性能调优的7个建议
Dec 28 Javascript
javascript中获取class的简单实现
Jul 12 Javascript
微信小程序开发(二)图片上传+服务端接收详解
Jan 11 Javascript
JavaScript实现设置默认日期范围为最近40天的方法分析
Jul 12 Javascript
node.js基于fs模块对系统文件及目录进行读写操作的方法详解
Nov 10 Javascript
分享5个小技巧让你写出更好的 JavaScript 条件语句
Oct 20 Javascript
深入理解js A*寻路算法原理与具体实现过程
Dec 13 Javascript
vue实现吸顶、锚点和滚动高亮按钮效果
Oct 21 Javascript
vue商城中商品“筛选器”功能的实现代码
Jul 01 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
简单的过滤字符串中的HTML标记
2006/12/25 PHP
php-accelerator网站加速PHP缓冲的方法
2008/07/30 PHP
php中文验证码实现示例分享
2014/01/12 PHP
PHP实现HTML生成PDF文件的方法
2014/11/07 PHP
php+flash+jQuery多图片上传源码分享
2020/07/27 PHP
use jscript Create a SQL Server database
2007/06/16 Javascript
常见浏览器多长时间会提示“脚本运行时间过长”总结
2014/04/29 Javascript
JavaScript删除数组元素的方法
2015/03/20 Javascript
JavaScript动态添加列的方法
2015/03/25 Javascript
bootstrap网页框架的使用方法
2016/05/10 Javascript
js倒计时显示实例
2016/12/11 Javascript
Javascript this 函数深入详解
2016/12/13 Javascript
bootstrap手风琴制作方法详解
2017/01/11 Javascript
JS常用倒计时代码实例总结
2017/02/07 Javascript
深入理解Vue生命周期、手动挂载及挂载子组件
2017/09/27 Javascript
微信小程序使用progress组件实现显示进度功能【附源码下载】
2017/12/12 Javascript
vue组件横向树实现代码
2018/08/02 Javascript
node.js中ws模块创建服务端和客户端,网页WebSocket客户端
2019/03/06 Javascript
微信小程序全局变量的设置、使用、修改过程解析
2019/09/24 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
Python使用MySQLdb for Python操作数据库教程
2014/10/11 Python
儿童编程python入门
2018/05/08 Python
Python中字符串String的基本内置函数与过滤字符模块函数的基本用法
2019/05/27 Python
python GUI库图形界面开发之PyQt5拖放控件实例详解
2020/02/25 Python
PyQt5中QSpinBox计数器的实现
2021/01/18 Python
Python爬虫+tkinter界面实现历史天气查询的思路详解
2021/02/22 Python
详解CSS3中使用gradient实现渐变效果的方法
2015/08/18 HTML / CSS
改变生活的男士内衣:SAXX Underwear
2019/08/28 全球购物
员工试用期自我鉴定范文
2014/09/15 职场文书
运动会表扬稿
2015/01/16 职场文书
2015年医药代表工作总结
2015/04/25 职场文书
忠犬八公的故事观后感
2015/06/05 职场文书
《梅花魂》教学反思
2016/02/18 职场文书
文明和谐家庭事迹材料(2016精选版)
2016/02/29 职场文书
竞聘演讲报告:基本写作有哪些?附开头范文
2019/10/16 职场文书
Python深度学习之实现卷积神经网络
2021/06/05 Python