【问题标题】:How to properly chain rxjs 6 observables?如何正确链接 rxjs 6 observables?
【发布时间】:2019-03-17 09:00:41
【问题描述】:

任何建议,如何以更承诺链接的方式重写?:

this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
        map(() => {
            return this.apiService.sendGetRequest('/api/users/' + this.currentUserId).pipe(
                map(data => {
                    return this.setActiveUser(data).pipe(
                        map(() => {
                            return this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId).pipe(
                                map(tasks => {
                                    return this.taskService.setCurrentUserTasks(tasks);
                                })
                            );
                        })
                    );
                })
            );
        })
    );

【问题讨论】:

    标签: angular rxjs observable rxjs6


    【解决方案1】:

    您可以使用switchMap 处理可观察对象,使用tap 处理副作用。你需要订阅,因为它是cold observable

    对于所有请求使用catchError 进行错误处理

    this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
        catchError(err=> this.errorHandler(err)),
        switchMap(() => this.apiService.sendGetRequest('/api/users/' + this.currentUserId)
            .pipe(catchError(err=> this.errorHandler(err)))
        ),
        tap(data => this.setActiveUser(data)),
        switchMap(() => this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId)
            .pipe(catchError(err=> this.errorHandler(err)))
        ),
        tap(tasks => this.taskService.setCurrentUserTasks(tasks))
    ).subscribe()
    

    【讨论】:

    • 为什么每个 switchMap 都需要 catchError()。为什么我们不能有一个?
    • 当粉碎一个可观察的整个流时会出现一个catchError。在这个解决方案中,当一个 observable 崩溃时,您可以获得部分数据。例如当this.apiService.sendGetRequest('/api/users/' + this.currentUserId)返回错误流将继续,你可以得到this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId)
    • 如果您不需要部分数据,请使用一个 catchError
    • 不需要有 catch 错误的嵌套管道。这些可以在主管道中管道
    【解决方案2】:

    为此使用SwitchMap

    mainApiCall.pipe(
        switchMap(result=>secondApiCall(result)),
        switchMap(resultFromSecondApiCall=>thirdApiCall(resultFromSecond))
    ...
    and so on
    )
    

    【讨论】:

    • 此代码示例中的命名选择是描述性的,有助于我快速理解链接在一起。这让我需要快速将各种 api 调用链接在一起。干杯!
    【解决方案3】:

    为您的问题使用单个 pipe。只需用逗号分隔不同的可链接运算符,例如 mapswitchMapmergeMaptap 等。

    this.apiService.sendPutRequest('/api/users/activate', usrObj).pipe(
      switchMap((results) => this.apiService.sendGetRequest('/api/users/' + this.currentUserId)),
      tap((results) => this.setActiveUser(data)),
      switchMap(() => this.apiService.sendGetRequest('api/tasks/user/' + this.currentUserId)),
      tap((results) => this.taskService.setCurrentUserTasks(tasks))
    );
    

    简化:如果您只想在没有任何异步 api 调用的情况下转换一个值并将其传递给另一个运算符或订阅,请使用 map,如果您只想在不转换的情况下捕获两者之间的值(例如,用于日志记录),请使用 tap )。 switchMap 用于调度额外的 api 调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      • 2017-01-06
      • 2016-09-07
      • 2016-08-18
      • 2018-05-11
      • 1970-01-01
      相关资源
      最近更新 更多