【问题标题】:How to run observable depends on previous observable's result with RxJS in Angular?如何运行 observable 取决于以前在 Angular 中使用 RxJS 的 observable 结果?
【发布时间】:2020-03-26 21:15:55
【问题描述】:

我需要做这些事情:

  • 从远程服务器中删除项目
  • 如果成功,从本地存储中删除项目
  • 如果成功,从远程服务器重新加载项目

现在我有了这段代码,但它运行不好,因为第三步没有运行。

delete(model: T, paginate: PaginateInterface): Observable<any> {
  return this.remoteStorageService.delete(model).pipe(map((resultDelete: boolean) => {
    if (resultDelete) {
      this.localStorageService.delete(model);
      return this.remoteStorageService.getAll().pipe(map( (resultGetAll: PaginateInterface) => {
        return resultGetAll;
      }));
    }

    return paginate;
  }));
}

我尝试使用 RxJS 的 switchMap 功能,但我完全迷路了。

如何运行一个函数取决于 observable 的结果,然后另一个 observable 返回结果?

【问题讨论】:

  • 您的 api 是否返回布尔值?您可以添加您尝试使用 switchMap 的代码吗?如果您的 api 失败,它不会返回错误响应状态代码 (500, 400 etcc...) 吗?
  • this.localStorageService的返回类型是什么?
  • 是的,实现取决于删除操作不成功时服务器返回的内容(错误通知是 400?代码还是 200,里面有一些对象?)
  • @Munzer remoteStorageService 处理所有错误。在节目的这一点上,这是不必要的。
  • @Picci this.localStorageService.delete() 是一个 void 函数 - 它处理自身内部可能出现的错误。

标签: angular rxjs rxjs6


【解决方案1】:

我假设步骤 1 和 3 是组件的工作,步骤 2 是服务的工作。

您可以使用tap 方法对可观察对象的成功或失败进行额外的逻辑处理:

服务:

deleteItem(model): Observable<any> {
  return this.http.delete<any>(`${yourUrl}`, model)
    .pipe(
      tap(result => {
        // success
        // delete from local storage here
      }, error => {
        // fail
        // in case you need logic for failure, put it here
      })
    );
}

组件:

delete(model) {
  this.yourService.deleteItem(model)
    .subscribe(result => {
      // success, local storage is updated at this point
      // reload your data
    }, error => {
      // fail, local storage was not updated
      // do your error handling logic here
    });
}

如果需要在组件中完成第 2 步,只需将 pipe 代码移动到您的组件即可。

【讨论】:

  • 这段代码在服务里面,是什么处理删除过程。给remoteStorageService.delete()下订单,如果成功,也请拨打localStorageService.delete()。然后也拨打remoteStorageService.getAll()。但是最后两个步骤仅在第一个返回 true 时发生
【解决方案2】:

根据您发布的代码和 cmets,我假设 remoteStorageService.deleteremoteStorageService.getAll() 返回一些 Observable,而 localStorageService.delete() 返回 void

如果是这种情况,您可以尝试类似的方法

delete(model: T, paginate: PaginateInterface): Observable<any> {
  return this.remoteStorageService.delete(model)
  .pipe(
     concatMap((resultDelete: boolean) => {
        if (resultDelete) {
           this.localStorageService.delete(model);
           return this.remoteStorageService.getAll();
        } else {
           return EMPTY  // if the delete fails you complete the Observable
           // you can also error here if you want to terminate the Observable with an error
        }
     })
  )
}

这里的关键是,首先你执行remoteStorageService.delete 并等待 Observable 通知它的结果。使用运算符concatMap 确保了包含在concatMap 中的Observable 仅在remoteStorageService.delete 通知其结果后才被执行(或更准确地说是订阅)。然后您可以使用remoteStorageService.delete 的结果来决定是返回remoteStorageService.getAll() 还是返回EMPTY

第一种情况remoteStorageService.getAll()是组件订阅的Observable,第二种情况EMPTY是组件订阅的Observable。 EMPY 是一个 Observable,它不发射任何东西并立即终止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    相关资源
    最近更新 更多