Как получить Observable <boolean>из Angular httpClient (true, если 200, false, если 404) - PullRequest
1 голос
/ 18 июня 2020

В angular у меня есть асинхронный c валидатор для формы регистрации пользователя, который проверяет, существует ли уже электронное письмо в базе данных. Он вызывает конечную точку моего Rest API с методом HEAD, который возвращает статус Http 200 Ok, если электронное письмо найдено, и 404, если оно не найдено (я не уверен, что это правильная мысль практики Rest). Но я не могу понять, как превратить этот http-вызов в Observable, которого ожидает мой валидатор.

Мои слои для этой операции, не принимая во внимание форму:

AsyncValidator -> authService.isEmailTaken () -> dataManagementService.headCall ()

Мой валидатор:

export const uniqueEmailValidator = (authService: AuthService, time: number = 500) => {
  return (input: FormControl) => {
    return timer(time).pipe(
      switchMap(() => authService.isEmailTaken(input.value)),
      map(isTaken => {
        console.log(isTaken);
        return isTaken ? { uniqueEmail: true } : null;
      })
    );
  };
};

AuthService.ts:

  public isEmailTaken(email: string): Observable<boolean> {
    const params = new Map();
      params.set('email', email);
      return this.dataManagementService.headResource(
        this.authURI + this.registerURI,
        params
      ).pipe(
        map(
         () => {
           console.log('success');
           return true;
         },
         () => {
           console.log('error');
           return false;
         }
     )
    );
  }

Мой http-вызов:

  public headResource(url: string, paramMap?: Map<string, string>): Observable<any> {
    const params = this.getHttpParams(paramMap);
    console.log('Sending HEAD request to server :');
    console.log(this.baseUrl + url);
    return this.httpClient.head(
      this.baseUrl + url,
      {params}
    );
  }

My validator should be valid when the status code is 404 and invalid when is 200, but though it works on 200, it has no efffect on 404. I'm not very confortable using rxjs.
Is there something i'm missing ? Or should i change the approach with the backend service sending a boolean, or maybe a 204 status code if not found ?
Thanks a lot for help!

============== РЕДАКТИРОВАТЬ =======================

Благодаря комментарию Мартина мне удалось заставить его работать, изменив метод isEmailTaken моего authService и используя catchError:

  public isEmailTaken(email: string): Observable<boolean> {
    const params = new Map();
    params.set('email', email);
    return this.dataManagementService.headResource(
      this.authURI + this.registerURI,
      params
    ).pipe(
      map(
      () => {
        return true;
      }),
      catchError(error => {
        if (error.status === 404) {
          return of(false);
        }
      })
    );
  }

1 Ответ

1 голос
/ 18 июня 2020

С Angular ответ HttpClient 404 будет преобразован в уведомление error, в то время как ваш валидатор ожидает boolean next уведомления. Итак, проблема в том, как превратить уведомление error в next. К счастью, это очень просто с оператором catchError():

import { of, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

this.httpClient.head().pipe(
  catchError(error => {
    if (error.status === 404) {
      return of(false); // emit `false` as next notification instead of the original error
    }
    return throwError(error); // rethrow other status codes as error
  }),
);

Кстати, map работает только с уведомлениями next. Я никак не справляюсь с error s.

...