Joh*_*lly 3 validation asynchronous operators rxjs angular-reactive-forms
当我出于某种原因按下表单输入上的按键时,异步验证器不会检测到distinctUntilChanged,并且它仍然发送API请求。例如,如果我按 35,删除 5,然后再次添加 5,它仍然会发送请求。这是代码:(我已经尝试了几乎所有方法,但仍然不起作用)
validateSomeNumber(control: FormControl): Observable<any> | Promise <any> {
    this.isSubmitBtnDisabled = true;
    return control.valueChanges.pipe(
      debounceTime(1000),
      distinctUntilChanged(),
      switchMap((value) => {
        return this.apiService.someApiRequest({ 'to_number': control.value }).pipe(
          map(res => {
            console.log(res);
            if (res.success) {
              // console.log(res);
              this.isSubmitBtnDisabled = false;
              return null;
            } else {
              // console.log(res);
              this.isSubmitBtnDisabled = true;
              return{ 'invalidCharacters': true };
            }
          }),
        );
      }),
      first()
    );
  }
默认情况下,validateSomeNumber每次值更改后都会调用。
如果您在每次值更改时返回此值
return control.valueChanges.pipe(
  debounceTime(1000),
  distinctUntilChanged(),
  ...
)
您正在为每个值变化创建一个新的可观察值变化。例如,如果您输入四个字符,您最终会得到四个独立的 Observable,每个 Observable 发出一个字符,而不是一个 Observable 发出四次。因此debounceTime和distinctUntilChanged只会影响您在特定值变化时创建的 Observable,但不会影响整个值变化过程。如果它们只影响 Observable 的发射,那么它们显然不会按照您的预期工作。
你应该直接返回http请求
validateSomeNumber(control: FormControl): Observable<any> | Promise <any> {
  this.isSubmitBtnDisabled = true;
  return this.apiService.someApiRequest({ 'to_number': control.value }).pipe(
      map(..),
  );
}
选项 1:更新
为了防止每次值更改时都执行 http 请求,Angular 建议将updateOn属性更改为submit或blur。
使用模板驱动的表单:
<input [(ngModel)]="name" [ngModelOptions]="{updateOn: 'blur'}">
对于反应形式:
new FormControl('', {updateOn: 'blur'});
{updateOn: 'blur'}仅当您的输入失去焦点时才会执行验证器。
选项 2:模拟 debounceTime 和distinctUntilChanged
如果表单值发生变化,Angular 会自动取消订阅 AsyncValidator 返回的上一个 Observable。这允许您使用 进行debounceTime仿真timer。要进行模拟,distinctUntilChanged您可以跟踪最后一个请求术语并自行进行相等性检查。
private lastRequestTerm = null;
validateSomeNumber(control: FormControl): Observable<any> | Promise <any> {
  this.isSubmitBtnDisabled = true;
  // emulate debounceTime
  return timer(1000).pipe(
    // emulate distinceUntilChanged
    filter(_ => control.value != this.lastRequestTerm),
    switchMap(() => {
      this.lastSearchTerm = control.value;
      return this.apiService.someApiRequest({ 'to_number': control.value });
    }),
    map(..)
  );
}
| 归档时间: | 
 | 
| 查看次数: | 1293 次 | 
| 最近记录: |