angular异步验证防抖踩坑实录

 更新时间:2019年12月01日 14:53:07   作者:笙歌会停  
这篇文章主要给大家介绍了关于angular异步验证防抖踩坑的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用angular具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

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

突然没了效果的验证功能

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

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

 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,而在方法中打印结果,却可以发现,能够产生正确的结果

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

FormControl的status

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

FormControl的status继承自AbstractControl

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

找到valid

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

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

为何会一直在pending状态?

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

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

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

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

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

如果你足够细心

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

一个更简单的实现方式

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

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

默认情况下,每当表单值变化之后,都会执行所有验证器。对于同步验证器,没有什么会显著影响应用性能的地方。不过,异步验证器通常会执行某种 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(),虽然因此浪费了不少的时间,但收获也是巨大的,这波不亏。

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

相关文章

  • Angular4的输入属性与输出属性实例详解

    Angular4的输入属性与输出属性实例详解

    这篇文章主要介绍了Angular4的输入属性与输出属性,结合实例形式详细分析了Angular4输入属性与输出属性的概念、功能及相关使用技巧,需要的朋友可以参考下
    2017-11-11
  • AngularJS中的promise用法分析

    AngularJS中的promise用法分析

    这篇文章主要介绍了AngularJS中的promise用法,结合实例形式分析了AngularJS异步处理模式promise具体功能、使用方法与相关注意事项,需要的朋友可以参考下
    2017-05-05
  • AngularJS ng-template寄宿方式用法分析

    AngularJS ng-template寄宿方式用法分析

    这篇文章主要介绍了AngularJS ng-template寄宿方式用法,结合实例形式分析了ng-template模板的相关使用技巧,需要的朋友可以参考下
    2016-11-11
  • AngularJS上拉加载问题解决方法

    AngularJS上拉加载问题解决方法

    这篇文章主要介绍了AngularJS上拉加载问题解决方法的相关资料,该问题在项目中一直存在,小编给大家分享解决办法,需要的朋友可以参考下
    2016-05-05
  • Angular.Js的自动化测试详解

    Angular.Js的自动化测试详解

    当Angular项目的规模到达一定的程度,就需要进行测试工作了。为什么要自动化测试?1,提高产出质量。2,减少重构时的痛。反正我最近重构多了,痛苦经历多了。3,便于新人接手。下面这篇文章就给大家详细介绍了Angular.Js的自动化测试,有需要的朋友们可以参考借鉴。
    2016-12-12
  • AngularJS ng-bind-template 指令详解

    AngularJS ng-bind-template 指令详解

    本文注意介绍AngularJS ng-bind-template 指令,这里把相关资料整理了一下,并附实例代码,有需要的小伙伴可以参考下
    2016-07-07
  • 使用ng-packagr打包Angular的方法示例

    使用ng-packagr打包Angular的方法示例

    这篇文章主要介绍了使用ng-packagr打包Angular的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • cnpm加速Angular项目创建的方法

    cnpm加速Angular项目创建的方法

    这篇文章主要介绍了cnpm加速Angular项目创建的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • AngularJS实现路由实例

    AngularJS实现路由实例

    本文给大家分享的是使用angularjs路由框架实现的一个简单页面跳转功能,非常的实用,也很详细,有需要的小伙伴可以参考下
    2017-02-02
  • AngularJS中使用HTML5手机摄像头拍照

    AngularJS中使用HTML5手机摄像头拍照

    这篇文章主要介绍了AngularJS中使用HTML5手机摄像头拍照的相关资料,需要的朋友可以参考下
    2016-02-02

最新评论