Angular 异步验证器进行多个 http 调用

问题描述 投票:0回答:1

我在 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}`);
}
angular rxjs asyncvalidators
1个回答
0
投票

每次表单运行验证器时都会调用从

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$;
    };
}

注意,我没有测试代码,但我相信您会明白的。

© www.soinside.com 2019 - 2024. All rights reserved.