Проблема в том, что новый канал создается каждый раз, когда validatorFn выполняется, когда вы вызываете pipe()
внутри validatorFn. Предыдущее значение не является записью для дискинта или отказов в работе. Что вы можете сделать, это настроить два BehaviourSubjects
внешне, termDebouncer
и validationEmitter
в моем случае.
Вы можете установить фабричный метод для создания этого валидатора и, тем самым, использовать его повторно. Вы также можете расширить AsyncValidator
и создать класс с настройкой DI. Я покажу фабричный метод ниже.
export function AsyncValidatorFactory(mockService: MockService) {
const termDebouncer = new BehaviorSubject('');
const validationEmitter = new BehaviorSubject<T>(null);
let prevTerm = '';
let prevValidity = null;
termDebouncer.pipe(
map(val => (val + '').trim()),
filter(val => val.length > 0),
debounceTime(500),
mergeMap(term => { const obs = term === prevTerm ? of(prevValidity) : mockService.checkValue(term);
prevTerm = term;
return obs; }),
map(respose => { invalid: true } : null),
tap(validity => prevValidity = validity)
).subscribe(validity => validationEmitter.next(validity))
return (control: AbstractControl) => {
termDebouncer.next(control.value)
return validationEmitter.asObservable().pipe(take(2))
}
}
Редактировать : Этот фрагмент кода взят из варианта использования, отличного от проверки угловых форм (точнее, для виджета React search), операторам конвейера, возможно, потребуется изменить в соответствии с вашим вариантом использования.
Edit2 : take(1)
или first()
, чтобы гарантировать, что наблюдаемое завершается после отправки сообщения проверки. asObservable()
обеспечит создание новой наблюдаемой при следующем вызове. Вы также можете пропустить asObservable()
и просто pipe()
, так как оператор канала разветвляет асинхронный конвейер и создает оттуда новую наблюдаемую область. Возможно, вам придется использовать take(2)
, чтобы обойти тот факт, что поведенческий объект является состоянием и содержит значение.
Edit3 : Используйте карту слияния, чтобы учесть тот факт, что distinctUntilChanged()
приведет к тому, что наблюдаемое не испустит и не завершится.