簡體   English   中英

在另一個可觀察對象中使用數據,然后將結果作為其他可觀察對象返回

[英]Use data from one observable in another and then return result as other observable

我正在解決這個問題:

申請流程:

我必須調用第一個 API 端點(為簡單起見,我們稱它為 EP-A),它將 Blob 作為正文,將 fileType 作為請求參數。 它通過調用自動生成的 class 來執行

  uploadFile$Response(params?: {
    fileType?: 'USER_AVATAR' | 'UNKNOWN' | 'DELIVERY_LOGO' | 'PAYMENT_LOGO' | 'ITEM_PICTURE';
    body?: { 'file'?: Blob }
  }): Observable<StrictHttpResponse<FileUploadResponse>> {

    const rb = new RequestBuilder(this.rootUrl, FileControllerService.UploadFilePath, 'post');
    if (params) {
      rb.query('fileType', params.fileType, {});
      rb.body(params.body, 'application/json');
    }

    return this.http.request(rb.build({
      responseType: 'blob',
      accept: '*/*'
    })).pipe(
      filter((r: any) => r instanceof HttpResponse),
      map((r: HttpResponse<any>) => {
        return r as StrictHttpResponse<FileUploadResponse>;
      })
    );
  }

StrictHttpResponse<T>只是一個包含“通用”主體的接口(因此您可以檢索具有由 swagger 定義的結構的數據,從該結構生成此方法)。

然后是 object 的結果FileUploadResponse

{
 uuid: string,
 time: Timestamp

 ...
 Other members omitted for simplicity
 ...
}

EP-A調用返回一個值之后立即發送到另一個 EP(我們稱之為EP-B ), EP-B將下面的 object 作為主體,並將當前記錄的人員作為路徑變量。

{
 uuid: string
}

因此,在調用 EP-B 之前,應解析來自 EP-A 的結果(在這種情況下,應獲取 uuid 字段並將其放入新的 object 以進行 EP-B 調用)

再次通過具有與上述簽名類似的簽名的生成方法(為簡單起見,我將省略它)。

如果一切正常,我想讓來電者知道這一點。 如果有任何失敗(這兩個 EP 調用中的任何一個),我想讓它知道調用此方法以做出某種反應(顯示警報,以某種方式更改頁面,...)

我現在使用的方法不完整,我不知道如何“連接”這兩個 Observable,我已經閱讀了有關 mergeMap、flatMap 等的信息,但我不確定如何在我的情況下使用它。

  updateUserAvatar(avatar: Blob): Observable<boolean> {

    return new Observable<boolean>((observer) => {

      // Calling EP-A
      this.avatarFormChangeRequestSubscription = this.fileControllerService.uploadFile$Response({
        fileType: 'USER_AVATAR',
        body: {
          file: avatar
        }
      })
        .subscribe((response: StrictHttpResponse<FileUploadResponse>) => {
            // Handle returned UUID and somehow pass it into an observable belog
            console.log(response);
          },
          (error: any) => {
            observer.error(error);
          });

      // Creating object for EP-B calling
      const avatarUpdateParams = {
        id: 1, // Just dummy ID for now, will be dynamically changed
        body: {
          avatarUUID: '' // the UUID from observable response above should be placed here
        }
      };

      // Calling EP-B
      this.avatarFormChangeRequestSubscription = this.userControllerService.updateUserAvatar$Response(avatarUpdateParams)
        .subscribe((response: StrictHttpResponse<string>) => {
          // Handle successfull avatar upload (change the "Logged user" object avatar to change it everywhere etc
          console.log(response);
          observer.next(true);
        },
          (error: any) => {
            observer.error(error);
          });
    });
  }

最后,我還想添加“用例”流程,以了解我要從用戶視圖中實現的目標:

用戶上傳他的照片,該照片首先上傳到BE端的文件系統(並與數據庫記錄鏈接),然后將該文件鏈接到他的個人資料作為他的個人資料圖片。

您可以使用rxjs來做到這一點。 類似的東西可能有效:

this.fileControllerService.uploadFile$Response({
    fileType: 'USER_AVATAR',
    body: {
      file: avatar,
    },
  })
  .pipe(
    tap((responseOfFirstApiCall: StrictHttpResponse<FileUploadResponse>) => {
      // Do whatever you want here, but you might not need that since you get the response below as well (in the flatMap)
      // Handle returned UUID and somehow pass it into an observable belog
      console.log(response);
    }),
    flatMap(
      (responseOfFirstApiCall: StrictHttpResponse<FileUploadResponse>) => {
        // Creating object for EP-B calling
        const avatarUpdateParams = {
          id: 1, // Just dummy ID for now, will be dynamically changed
          body: {
            avatarUUID: '', // the UUID from observable response above should be placed here
          },
        };

        return this.userControllerService.updateUserAvatar$Response(avatarUpdateParams);
      }
    ),
    tap((responseOfTheSecondApiCall: StrictHttpResponse<string>) => {
      // Handle successfull avatar upload (change the "Logged user" object avatar to change it everywhere etc
      console.log(response);
      observer.next(true);
    }),
    catchError((err: any) => of(err))
  )
  .subscribe(); // Empty subscribe() call to trigger the http request. Not needed if you get the result somewhere else (eg if your method return an observable that you want to handle the result somewhere else)

flatMap()與 mergeMap 相同。 根據需要更改它,有很多選項,例如mapswitchMap ,您應該了解它們,因為它們很有用。

基本上, pipe允許您鏈接函數,如果有錯誤,則觸發catchError

提示:請注意,在pipe調用的結果之前執行 pipe 中的內容。 因此,如果您想在獲得結果之前對結果做一些事情,那么請考慮rxjs

服務

getUser(id: string) {
  return this._http.get<any>(url).pipe(
    map(result => result.email), // Return only the email
  );
}

零件:

  ngUnsubscribe = new Subject();

  ngOnInit() {
    this._userService.getUser(1)
    .pipe(takeUntil(this.ngUnsubscribe)) // Don't forget to unsubscribe !
    .subscribe(email => console.log('email = ', email))
  }

  ngOnDestroy() {
    this.ngUnsubscribe.unsubscribe();
    // or
    // this.ngUnsubscribe.next();
    // this.ngUnsubscribe.complete();
  }

暫無
暫無

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

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