'DebounceTime emits all the events which was captred during the time

I need to write the async validator for the reactive form type in angular. I have implemented it trough promise. But the issue is the validator triggers for each keystroke it strike the server for every keystroke.For implementing the debounce i have implemented the setTimeout for the promise but the issue i faced is it triggers for after the certain millisecon i have defined. Finally I have implemented the Observable inside the promise to achive all debounceTime, But the issue i faced here is the debounceTime emits all the events. For example: If I type 'Prem' from input field the following code triggers the server for four time as timeout works.

If any issue in implemetation of the async validator please clarify me.

//Latest code
static hasDuplicateEmail(formControl: FormControl) {
        return new Promise((resolve, reject) => {
            return new Observable(observer => 
               observer.next(formControl.value)).pipe(
                debounceTime(600),
                distinctUntilChanged(),
                switchMap((value) => {
                    //server side
                    return MotUtil.fetch('checkForRegisterEmail', {e: formControl.value});
                })
            ).subscribe((res) => {
                return (JSONUtil.isEmpty(res)) ? resolve(null) : resolve({duplicate: true});
            });
        });
    }

The debounceTime should work as mentioned in the Docs.



Solution 1:[1]

You are trying to approach it in a difficult way. Validator takes argument - AbstractControl. AbstractControl has property - valueChanges which return stream of changes in your formControl. So here you add debouceTime and later do other operations and finaly return this stream back to FormControl:

hasDuplicateEmail(control: AbstractControl) {
  return control.valueChanges.pipe(
    debounceTime(600),
    switchMap(e => 
      this.http.get('checkForRegisterEmail', {e}).pipe(
        map((res: any) => JSONUtil.isEmpty(res) ? null : { duplicate: true })
      )
    )
  )
}

As you notice I use HttpClient as it is the way you make HTTP calls in Angular (it is designed to work on streams rather then Promises)

Solution 2:[2]

emailValidator(/** params that you need inside switchMap */): AsyncValidatorFn {
    return (control: AbstractControl): Observable<ValidationErrors | null> => {
        return of(control.value).pipe(
            delay(500), //for me works with delay, debounceTime are not working with asyncValidator
            filter(email=> !!email), //length or another logic there is not emails with less than 10 characters
            distinctUntilChanged(),
            switchMap(/** as you need */),
            map(exist => (exist ? {duplicate: true} : null)),
            catchError(() => of(null))
        );
    };
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Julius Dzidzevi?ius
Solution 2