Подписка на наблюдаемые 2 типа на Angular - PullRequest
0 голосов
/ 31 марта 2020

Извините за заголовок, но я не смог найти лучшего.

Я вызываю HTTP API, который возвращает объект json при отправке команды GET, но он возвращает 404, если ресурс не был найден. Я использую Angular 9 и пытаюсь найти способ вывести объект json из сервиса или вернуть значение enum полученной ошибки HTTP на том же Observable.

Пожалуйста, см. следующий код:

device.service.ts

getDevice(objectID: number | string): Observable<Device | ResponseStatus> {
    return this.http.get<Device>(`http://localhost:8080/Registration/Device/${objectID}`)
      .pipe(
        catchError(this.handleError)
      );
  }
handleError(error: HttpErrorResponse): Observable<ResponseStatus> {
    switch (error.status) {
      case 404: {
        return of(ResponseStatus.objectNotFound);
        break;
      }
      case 409: {
        return of(ResponseStatus.objectAlreadyExists);
        break;
      }
    }
  }

I wi sh для возврата ResponseStatus моим компонентам, поэтому я могу обрабатывать все ошибки одинаково .

device-item-resolver-service.ts

export class DeviceItemResolverService implements Resolve<Device> {

  constructor(private ds: DeviceService, private router: Router) { }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Device> | Observable<never> {

    let objectID = route.paramMap.get('objectID');

    return this.ds.getDevice(objectID).pipe(
      take(1),
      mergeMap(
        (item: Device) => {
          if (item) {
            return of(item);
          }
          else {
            this.router.navigate(['/devices']);
            return EMPTY;
          }
        }
      )
    );
  }
}

Очевидно, все идет хорошо. Запустив программу, я могу получить Устройство, но не могу найти способ обработки ResponseStatus на распознавателе.

Пожалуйста, не могли бы вы мне помочь?

Ответы [ 2 ]

0 голосов
/ 01 апреля 2020

Я не смог использовать typeof или instanceof, как было предложено, поэтому я нашел отличный документ о расширенных типах в машинописи, следующий: https://www.typescriptlang.org/docs/handbook/advanced-types.html#user -defined-type-guard-ы

См. Ниже, как я решил эту проблему:

Сначала я определил определяемый пользователем тип защиты:

function isDevice(value: Device | ResponseStatus): value is Device {
      return (value as Device).objectID !== undefined;
    }

Затем я вызвал эту функцию для своего исходного кода:

return this.ds.getDevice(objectID).pipe(
      take(1),
      mergeMap(
        (item: Device | ResponseStatus) => {
          if (!item) {
            this.router.navigate(['/devices']);
            return EMPTY;
          }
          else if (isDevice(item)) {
            return of(item)
          }
          else {
            switch (item as ResponseStatus) {
              case ResponseStatus.objectNotFound: {
                this.router.navigate(['/devices']);
                return EMPTY;
              }
            }
          }
        }
      )
    )        
  }

Обратите внимание, что мне нужно использовать mergeMap. map не работал.

0 голосов
/ 01 апреля 2020

Использование mergeMap не требуется, поскольку map должно быть достаточно хорошим в этом случае.

import { map } from 'rxjs/operators';
....
return this.ds.getDevice(objectID).pipe(
      take(1),
      map(
        (item: Device | ResponseStatus) => {
          // this if statement I think is the culprit.
          // Basically ResponseStatus.objectNotFound is true and it goes here
          // I am not sure if instanceof will work but basically you have to find out 
          // if you're getting Device or ResponseStatus and act accordingly
          if (item instanceof Device) {
            return item;
          }
          else {
            this.router.navigate(['/devices']);
            return null;
          }
        }
      )
    );
...