簡體   English   中英

在 Angular 上訂閱 2 種類型的 observable

[英]Subscribing to observable of 2 types on Angular

對不起,標題,但我找不到更好的。

我正在調用一個 HTTP API,它在發送 GET 命令時返回一個 json 對象,但如果找不到資源,它將返回 404。 我正在使用 Angular 9,我正在嘗試找到一種方法來從服務輸出 json 對象或在同一個 Observable 上返回接收到的 HTTP 錯誤的枚舉值。

請看下面的一些代碼:

設備服務.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;
      }
    }
  }

我希望將 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 的方法。

拜托,你能幫我嗎?

不需要使用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;
          }
        }
      )
    );

我不能按照建議使用typeofinstanceof ,所以我在打字稿中找到了一個關於高級類型的很棒的文檔,如下: https : //www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type -守衛

下面看看我是如何解決這個問題的:

首先我定義了一個用戶定義的類型保護:

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沒有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM