我在 Angular 应用程序中有一个自定义异步验证器,用于验证值的唯一性。验证器对后端 API 进行 HTTP 调用。我试图通过添加
distinctUntilChanged
和 debounceTime
来控制 API 调用的数量,但这似乎效果不佳。每次击键都会发出呼叫。
我哪里出错了?
我尝试使用控件的 valueChanges 并且一切正常,但我有一个用例,我需要通过单击表单上的单个按钮来运行所有验证器以检查错误,有没有办法在表单上运行所有验证器不考虑价值变化?
使用我当前的方法,我可以通过单击一个按钮来运行所有验证,但它不遵守 RxJS 运算符。
function uniqueAltIdValue(type, productId): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors | null> => {
const value: string = control.value;
return validateValue(type, value).pipe(
distinctUntilChanged(),
debounceTime(800),
map((response: { id: string; isValid: boolean }) =>
(productId.toLowerCase() !== response.id.toLowerCase() && !response.isValid)
? { valueExists: true }
: null,
),
catchError(() => of({ valueExists: true })),
);
};
}
function validateValue(type: string, value: string): Observable<{ id: string; isValid: boolean }> {
return this._httpService.requestCall(`${this.url}?type=${type}&id=${value}`);
}
每次表单运行验证器时都会调用从
uniqueAltIdValue()
返回的函数,因此在您的情况下,您每次都会创建一个单独的链。反过来,这意味着每次执行验证器时,您都会创建一个新的 Observable,这就是为什么 distinctUntilChanged()
或 debounceTime()
在您的情况下没有效果。
您可以做的是返回一个
Subject
,然后在需要运行验证时将值推入其中。您还想在 validateValue()
和 deboucneTime()
之后致电 distinctUntilChanged()
。
function uniqueAltIdValue(type, productId): AsyncValidatorFn {
const subject = new Subject();
const validate$ = subject.pipe(
distinctUntilChanged(),
debounceTime(800),
switchMap(() => validateValue(type, value)),
map((response: { id: string; isValid: boolean }) =>
(productId.toLowerCase() !== response.id.toLowerCase() && !response.isValid)
? { valueExists: true }
: null,
),
catchError(() => of({ valueExists: true })),
)
return (control: AbstractControl): Observable<ValidationErrors | null> => {
subject.next(control.value);
return validate$;
};
}
注意,我没有测试代码,但我相信您会明白的。