如何使用 RxJS observable 去抖动 Angular 4 中的异步验证器? [英] How to debounce async validator in Angular 4 with RxJS observable?

查看:19
本文介绍了如何使用 RxJS observable 去抖动 Angular 4 中的异步验证器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有 Angular 4 反应式表单的自定义异步验证器来检查电子邮件地址是否已通过调用后端获取.

I'm using custom async validator with Angular 4 reactive forms to check if E-Mail address is already taken by calling a backend.

然而,Angular 会调用验证器,它会为每个输入的字符向服务器发出请求.这会给服务器带来不必要的压力.

However, Angular calls the validator, which makes request to the server for every entered character. This creates an unnecessary stress on the server.

是否可以使用 RxJS observable 优雅地消除异步调用?

Is it possible to elegantly debounce async calls using RxJS observable?

import {Observable} from 'rxjs/Observable';

import {AbstractControl, ValidationErrors} from '@angular/forms';
import {Injectable} from '@angular/core';

import {UsersRepository} from '../repositories/users.repository';


@Injectable()
export class DuplicateEmailValidator {

  constructor (private usersRepository: UsersRepository) {
  }

  validate (control: AbstractControl): Observable<ValidationErrors> {
    const email = control.value;
    return this.usersRepository
      .emailExists(email)
      .map(result => (result ? { duplicateEmail: true } : null))
    ;
  }

}

推荐答案

虽然@Slava 的答案是正确的.使用 Observable 更容易:

While @Slava's answer is right. It is easier with Observable :

return (control: AbstractControl): Observable<ValidationErrors> => {
      return Observable.timer(this.debounceTime).switchMap(()=>{
        return this.usersRepository
            .emailExists(control.value)
            .map(result => (result ? { duplicateEmail: true } : null));
      });
}

使用现代 RxJS 进行更新:

return (control: AbstractControl): Observable<ValidationErrors> => {
    return timer(this.debounceTime).pipe(
        switchMap(()=>this.usersRepository.emailExists(control.value)),
        map(result => (result ? { duplicateEmail: true } : null))
    );
}

注意事项:

  • Angular 会自动取消订阅返回的 Observable
  • timer() 带一个参数只会发出一项莉>
  • 因为 timer 只发出一个值,所以我们使用 switchMap 还是 flatMap
  • 并不重要
  • 您应该考虑使用 catchError 以防服务器调用失败
  • 角度文档:异步验证
  • Angular will automatically unsubscribe the returned Observable
  • timer() with one argument will only emit one item
  • since timer emits only one value it does not matter if we use switchMap or flatMap
  • you should consider to use catchError in case that the server call fails
  • angular docs: async-validation

这篇关于如何使用 RxJS observable 去抖动 Angular 4 中的异步验证器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆