我的编程空间,编程开发者的网络收藏夹
学习永远不晚

angular异步验证器防抖的方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

angular异步验证器防抖的方法

本篇内容介绍了“angular异步验证器防抖的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    背景:

    当前输入框的formControl设置了异步验证器,会根据当前的值进行请求后台,判断数据库中是否存在。

    angular异步验证器防抖的方法

    原版异步验证器:

    vehicleBrandNameNotExist(): AsyncValidatorFn {    return (control: AbstractControl): Observable<ValidationErrors | null> => {      if (control.value === '') {        return of(null);      }      return this.vehicleBrandService.existByName(control.value).pipe(map(exists => exists ? {vehicleBrandNameExist: true} : null));    };  }

    但是测试下来发现,该异步验证器触发的太频繁了。输入框每输入一个字母都会对后台进行请求,不利于节省资源。

    防抖节流

    这个相关的操作叫做防抖和节流。什么是防抖和节流?有什么区别?

    本质上是一种优化高频率执行代码的一种手段。

    比如浏览器的鼠标点击,键盘输入等事件触发时,会高频率地调用绑定在事件上的回调函数,一定程度上影响着资源的利用。

    为了优化,我们需要 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率。

    定义:

    防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

    节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

    举个例子来说明:

    乘坐地铁,过闸机时,每个人进入后3秒后门关闭,等待下一个人进入。

    闸机开之后,等待3秒,如果中又有人通过,3秒等待重新计时,直到3秒后没人通过后关闭,这是防抖

    闸机开之后,每3秒后准时关闭一次,间隔时间执行,这是节流

    代码实现:

    防抖操作恰好符合我们的需求。

    找异步验证器中防抖的代码实现中恰好看到了liyiheng学长的文章:
    https://www.yisu.com/article/175497.htm,于是便参考了一下。

    这里仅是说明angular中formContorl异步验证器如何防抖的步骤:

    创建(改写)异步验证器

    vehicleBrandNameNotExist(): AsyncValidatorFn {    return (control: AbstractControl): Observable<ValidationErrors | null> => {      if (control.value === '') {        return of(null);      }      return control.valueChanges.pipe(        // 防抖时间,单位毫秒        debounceTime(1000),        // 过滤掉重复的元素        distinctUntilChanged(),        // 调用服务, 获取结果        switchMap(value => this.vehicleBrandService.existByName(value)),        // 对结果进行处理,null表示正确,对象表示错误        map((exists: boolean) => (exists ? {vehicleBrandNameExist: true} : null)),        // 每次验证的结果是唯一的,截断流        first()      )    };  }
    • 添加异步验证器

    let formControl = new FormControl('', [], asyncValidate.vehicleBrandNameNotExist());

    之后我们在v层在相关的标签上绑定该fromControl就可以了。

    疑惑

    相关操作到这里就结束了,能够正常使用了。

    但是改写之后还有些疑惑。

    原来的版本是这么使用的:

    return this.vehicleBrandService.existByName(...)

    改写后是这么使用的:

    return control.valueChanges.pipe(...

    改写后使用了valueChanges,也就是产生了一个observable,它使得每当控件的值在更改时,它都会发出一个事件。

    那么,每次调用异步验证器之后,我们每次都用valueChanges,每次的observable是不是同一个?

    于是我进行了测试:
    原理:多次调用异步验证器,并缓存ovservable,如果不相同则输出 “不相等”

    angular异步验证器防抖的方法

    测试结果:如图,只是在第一次初始化的时候输出了不相等,因为第一次observable为undefined, 在有值之后,多次调用异步验证器发现observabel始终是同一个

    angular异步验证器防抖的方法

    first()的使用

    之前也不理解first的使用,看学长的文章之后才明白,first()来避免多次地这样返回值。

    angular异步验证器防抖的方法

    所以我们产生的observable一直处于pending状态,需要用first让它返回第一个值就好。

    return control.valueChanges.pipe(           first() )

    单元测试

    一个好的功能要有一个好的单元测试。

    1 it('should create an instance', async () => { 2   expect(asyncValidate).toBeTruthy(); 3   let formControl = new FormControl('', [], asyncValidate.vehicleBrandNameNotExist()); 4   formControl.setValue('重复车辆品牌'); 5    // 等待防抖结束 6   await new Promise(resolve => setTimeout(resolve, 1000)); 7   getTestScheduler().flush(); 8   expect(formControl.errors.vehicleBrandNameExist).toBeTrue();     ...}));

    原来的时候我写的单元测试说这样的,

    等待防抖结束我用了await new Promise 以及setTimeout。执行到第8行的时候,让线程等待1秒。

    经过老师指正之后,发现这样并不好。假如某个测试需要等待一个小时,那么我们的执行时间就需要1个小时,这显然是不现实的。

    所以这里用到了fakeAsync;

    fakeAsync;

    fakeAsync,字面上就是假异步,实际上还是同步进行的。

    使用tick()模拟时间的异步流逝。

    官方测试代码:

    angular异步验证器防抖的方法

    仿照测试代码:

    我在tick()前后,打印了new Date(),也就是当时的时间,结果是什么呢?

    angular异步验证器防抖的方法

    可以看到第一个打印了17:19:30,也就是当时测试的时间。

    但是在tick(10000000)后,打印的时间是20:06:10, 达到了一个未来的时间。

    并且,这两条语句几乎是同时打印的,也就是说,单元测试并没有让我们真的等待10000000ms。

    angular异步验证器防抖的方法

    所以经过测试时候我们就可以使用tick(1000)和fakeAsync模拟防抖时间结束了。

    it('should create an instance', fakeAsync( () => {    expect(asyncValidate).toBeTruthy();    let formControl = new FormControl('', [], asyncValidate.vehicleBrandNameNotExist());    formControl.setValue('重复车辆品牌');    // 等待防抖结束    tick(1000);    getTestScheduler().flush();    expect(formControl.errors.vehicleBrandNameExist).toBeTrue();  }));

    题外

    写后台的时候还遇到了一个错误:

    angular异步验证器防抖的方法

    它说我color没有设置默认值,但是回去一看明明已经设置了。

    angular异步验证器防抖的方法

    打了很多断点都没发现问题。

    后来到数据库一看,好家伙,怎么有两个,一个是colour,一个是color.

    angular异步验证器防抖的方法

    之后翻看之前提交的代码,发现是之前用的是color,后面换成了colour。

    但是我jpa hibernate设置的是update,所以数据库对应执行的是更新,所以上次的字段并没有删除,这才导致了数据库有两个字段。之后删除其中一个了就没事了。

    jpa:    hibernate:      ddl-auto: update

    补充

    后面谷歌之后发现了一种比较简洁也好理解的方法:

    不用调用first()之类的操作符, 把timer()的返回值作为一个observable就可以了。

    time的作用在这里:
    https://rxjs-cn.github.io/lea...

    简单来说就是当 timer 结束时发出一个值。

    这个原理猜测可能是当timer还没有结束并重复调用异步验证器时,表单就不管这个timer了,转而关注新的。

    当然只是猜测,有机会再补充,经过测试防抖功能是正常的。

    export class VehicleBrandAsyncValidator {    debounceTime = 1000;    constructor(private vehicleBrandService: VehicleBrandService) { }    vehicleBrandNameNotExist(): AsyncValidatorFn {    return (control: AbstractControl): Observable<ValidationErrors | null> => {      if (control.value === '') {        return of(null);      }      return timer(this.debounceTime).pipe(        // 调用服务, 获取结果        switchMap(() => this.vehicleBrandService.existByName(control.value)),        // 对结果进行处理,null表示正确,对象表示错误        map((exists: boolean) => (exists ? {vehicleBrandNameExist: true} : null)),      )    };  }}

    “angular异步验证器防抖的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    angular异步验证器防抖的方法

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    angular异步验证器防抖的方法

    本篇内容介绍了“angular异步验证器防抖的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景:当前输入框的formControl设置
    2023-06-29

    PHPCMS验证码显示异常的解决方法

    标题:PHPCMS验证码显示异常的解决方法随着网络的普及和发展,网站安全问题变得愈加重要。在网站注册、登录等操作中,验证码是一种常见的安全验证手段,能够有效防止机器人恶意攻击。在使用PHPCMS搭建网站时,有时候会遇到验证码显示异常的问题
    PHPCMS验证码显示异常的解决方法
    2024-03-12

    阿里云账户验证服务器异常原因、解决方法及预防措施

    阿里云作为全球领先的云计算服务提供商,为广大用户提供稳定、高效的云计算服务。然而,最近有用户反映阿里云账户验证服务器出现异常,导致用户无法正常使用阿里云服务。本文将对这一问题进行详细解析,并提供相应的解决方法和预防措施。一、阿里云账户验证服务器异常原因分析服务器故障:服务器故障是导致阿里云账户验证服务器异常的常见
    阿里云账户验证服务器异常原因、解决方法及预防措施
    2023-11-04

    阿里云服务器身份验证异常的解决方法

    阿里云服务器是一款性能稳定、安全可靠的云计算产品。然而,有时在使用过程中可能会遇到一些问题,如身份验证异常。本文将详细介绍如何解决阿里云服务器身份验证异常的问题。阿里云服务器身份验证异常是指在使用阿里云服务器时,无法进行正常的身份验证操作,导致无法正常使用服务器。这可能是因为服务器配置错误、网络问题、服务器端问题
    阿里云服务器身份验证异常的解决方法
    2023-11-06

    Android本地验证码的简易实现方法(防止暴力登录)

    0. 前言 验证码无处不在,有人问我,你知道达芬奇密码下面是什么吗,对,答案就是达芬奇验证码。 验证码一个最主要的作用就是防止恶意暴力破解登录,防止不间断的登录尝试,有人说其实可以在服务器端对该终端进行登录间隔检测,如果间隔太短可以展示
    2022-06-06

    阿里云防止服务器异地登录的设置方法

    本文将详细介绍阿里云防止服务器异地登录的设置方法,包括基本步骤、需要的工具和配置步骤等,帮助您更好地管理您的服务器。阿里云服务器异地登录的设置方法阿里云服务器是阿里云提供的一种高性能计算服务,它提供了一种简单高效的方式来管理和运行你的应用。然而,随着阿里云服务器的广泛使用,服务器异地登录问题逐渐显现出来。异地登录
    阿里云防止服务器异地登录的设置方法
    2023-10-29

    解决阿里云服务器远程桌面连接身份验证错误问的方法

    本文将介绍如何解决在使用阿里云服务器时,远程桌面连接出现身份验证错误的问题。我们将探讨可能的原因,并提供几种解决方法,帮助用户快速恢复远程桌面连接。在使用阿里云服务器时,有时会遇到远程桌面连接出现身份验证错误的情况。这种情况通常是由于连接配置错误或服务器设置不当导致的。下面是一些常见的解决方法:方法一:检查远程桌
    解决阿里云服务器远程桌面连接身份验证错误问的方法
    2024-01-15

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录