繁体   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