我有点理解,其中涉及的工具将是pipe
,timer
,switchMap
,debounceTime
,distinctUntilChanged
,甚至可能更多,但是我无法弄清楚如何使它们与combineLatest
一起使用。
以下验证器获取以逗号分隔的电子邮件列表,并对每个电子邮件执行API调用,以检查客户数据库中是否存在该电子邮件。
import {AbstractControl, AsyncValidatorFn, ValidationErrors, ValidatorFn} from "@angular/forms";
import {combineLatest} from "rxjs";
import {Observable} from "rxjs/internal/Observable";
import {UtilityApiService} from "../../services/api/utility-api.service";
/**
* The email address must exist in the database and belong to a customer.
* It works both with a single email or a comma separate list of emails. In case of a list, it will only validate
* as a success if ALL emails belong to a customer.
* @returns {ValidatorFn}
* @constructor
*/
export class CustomerEmailCsvValidator {
public static createValidator(internalApiService: UtilityApiService): AsyncValidatorFn {
return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
return new Observable((observer) => {
if (!control.value) {
observer.next(null);
return;
}
const emails: string[] = control.value.split(",").map(email => email.trim());
const observables: Observable<boolean>[] = emails.map(email => {
return internalApiService.isCustomerEmail(email);
});
combineLatest(observables).subscribe((responses: boolean[]) => {
if (responses.every(value => value)) {
// All emails exist and belong to customers. Therefore no error.
observer.next(null);
} else {
// One or more emails do not exist in the database, or do not belong to a customer.
// This is an error for this validator.
observer.next({customerEmail: true});
}
observer.complete();
});
});
};
}
}
如何消除抖动,以使其在750毫秒内不多次运行API调用?
答案 0 :(得分:0)
这对我最终有用:
import {AbstractControl, AsyncValidatorFn, ValidationErrors, ValidatorFn} from "@angular/forms";
import {combineLatest, of, timer} from "rxjs";
import {Observable} from "rxjs/internal/Observable";
import {map, switchMap} from "rxjs/operators";
import {UtilityApiService} from "../../services/api/utility-api.service";
/**
* The email address must exist in the database and belong to a customer.
* It works both with a single email or a comma separated list of emails. In case of a list, it will only validate
* as a success if ALL emails belong to a customer.
* @returns {ValidatorFn}
* @constructor
*/
export class CustomerEmailCsvValidator {
public static createValidator(internalApiService: UtilityApiService): AsyncValidatorFn {
return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
return timer(750).pipe(switchMap(() => {
if (!control.value) {
return null;
}
const emails: string[] = control.value.split(",").map(email => email.trim());
const observables: Observable<boolean>[] = emails.map(email => {
return internalApiService.isCustomerEmail(email);
});
return combineLatest(observables).pipe(map((responses: boolean[]) => {
if (responses.every(value => value)) {
// All emails exist and belong to customers. Therefore no error.
return null;
} else {
// One or more emails do not exist in the database, or do not belong to a customer.
// This is an error for this validator.
return {customerEmail: true};
}
}));
}));
};
}
}