Наблюдаемое преобразование для обработки ошибки внутреннего сервера - PullRequest
0 голосов
/ 25 мая 2020

Приносим извинения за вопрос новичка / дамп о Rx JS, только начатый, так как я изучаю Angular.

Итак, я создал метод c асинхронного валидатора, который вызывает службу API метод проверки уникальности имени пользователя в базе. Приведенные ниже фрагменты кода работают, когда внутренний сервер запущен и работает. Когда это не так, он печатает сообщение журнала ошибок, которое я должен обрабатывать в компоненте презентации. От 1006 * до Observable<ValidationErrors | null>.

Validator

static usernameUnique(service: ApiService): AsyncValidatorFn {
    return (control: FormControl): Observable<ValidationErrors | null> => {
        return service.isUsernameTaken(control.value as string)
            .pipe(
                map((response: SuccessResponse) => response.data ? { taken: true } : null)
            );
    };
}

ApiService

isUsernameTaken(username: string): Observable<SuccessResponse | ErrorResponse> {
    return this.httpCient.get('/backend/account/checkUnique', { params: { username: username } })
                .pipe(catchError(this.handleError));
}

handleError(error: HttpErrorResponse) : Observable<ErrorResponse> {
    // return specific payload of ErrorResponse based on error.status
}

Заранее спасибо.

1 Ответ

3 голосов
/ 25 мая 2020

Я не совсем уверен, где вы столкнулись с проблемой. Если вы пытаетесь разрешить карту в ValidationErrors внутри валидатора, вам нужно будет проверить тип. В этом примере я возвращаю ошибку с именем "apiError", чтобы отличить ее от ошибки "принято", но я не уверен, как вы решите обработать этот случай в своем приложении.

Я предполагаю, что ErrorResponse содержит поле error, а SuccessResponse содержит поле data.

static usernameUnique(service: ApiService): AsyncValidatorFn {
  return (control: FormControl): Observable<ValidationErrors | null> => {
    return this.isUsernameTaken(control.value as string)
      .pipe(
        map(response => {
          if ('error' in response) { // response is ErrorResponse
            return { apiError: response.error };
          }
          return response.data ? { taken: true } : null;
        })
      );
  };

Если вы создаете фактические экземпляры класса, используя new ErrorResponse() и new SuccessResponse() вы можете использовать intanceof вместо проверки полей с помощью оператора in. например, if (response instanceof ErrorResponse).

В качестве альтернативы , вы можете передать ошибку обратно валидатору и обработать ответ в другом catchError. Я предпочитаю этот способ, потому что в ответе от API нет условного logi c.

Validator

static usernameUnique(service: ApiService): AsyncValidatorFn {
  return (control: FormControl): Observable<ValidationErrors | null> => {
    return this.isUsernameTaken(control.value as string)
      .pipe(
        map(response => response.data ? { taken: true } : null),
        catchError((err: ErrorResponse) => of({ apiError: err.error }))
      );
  };
}

ApiService

isUsernameTaken(username: string): Observable<SuccessResponse> {
  return this.http.get('/backend/account/checkUnique', { params: { username } })
    .pipe(
      map(response => response as SuccessResponse), // maps the api response to SuccessResponse
      catchError(this.handleError) // maps the error to ErrorResponse
    );
}

handleError(error: HttpErrorResponse): Observable<never> {
  let errorResponse: ErrorResponse;
  // specific payload of ErrorResponse based on error.status

  return throwError(errorResponse);
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...