【问题标题】:convert nested AngularJS service to Angular Observable service将嵌套的 AngularJS 服务转换为 Angular Observable 服务
【发布时间】:2021-06-22 00:41:38
【问题描述】:

我在 Angular(11) 中重建的项目中有一些使用嵌套调用的 AngularJS(pre 1.5) 服务。 这些服务使用嵌套调用,但我不知道如何使用 RXJS 重建它们。

任何帮助或详细链接来了解我如何获得所需的结果都会很棒。 到目前为止,我还没有找到任何可以帮助我了解如何解决此问题的内容。

这是原始服务:

function getBalanceGroups() {
            return $http.get(url.format("/accounts/{{accountId}}/balance-groups", $stateParams))
                .then(function (response) {
                    _.each(response.data, function (item) {
                        getBalanceViews(item.accountBalanceGroupId)
                            .then(function (balanceViewData) {
                                item.balanceViews = _.sortBy(balanceViewData, function (view) {
                                    return (view.balanceViewId === item.totalIndebtednessViewId) ? 0 : 1;
                                });
                                _.each(item.balanceViews, function (view) {
                                    getBalanceSegments(view.accountBalanceViewId)
                                        .then(function (balanceSegmentData) {
                                            view.balanceSegments = balanceSegmentData;
                                            view.totalBalance = 0;
                                            view.totalBalance = _.sumBy(view.balanceSegments, "balance");
                                        });
                                });
                            });
                    });
                    response.data = _.sortBy(response.data, function (item) {
                        return (item.isActive && item.isPrimary) ? 0 : 1;
                    });
                    return new LinkedList(response.data);
                }, function (error) {
                    $log.error('Unable to return balance group for the balanceChiclet');
                });
        }

这是我到目前为止的:(不工作 - 它正在返回最终的api数据响应,我需要使用数据来使用数据来修改之前的响应并返回修改后的数据。不知道如何)

getBalanceGroups(accountId: number | string): Observable<any> {
    let balGroupsUrl = `/accounts/${accountId}/balance-groups`;
    return this.http.get(`${this.baseUrl}${balGroupsUrl}`).pipe(
      mergeMap( (groups: any) => groups),
      flatMap((group:any) => {
        group.balanceViews = [];
        
        return this.getBalanceViews( group.accountBalanceGroupId, group )

      }),
      mergeMap( (views: any) => views),
      flatMap((views: any) => {
        return this.getBalanceSegments( views.accountBalanceViewId )
      }),

      catchError((err) => of(err) ),

      tap( groups => console.log('groups: 3:', groups) ),
    )

  }

private getBalanceViews(accountBalanceGroupId: number | string, group): Observable<any> {
    let balViewsUrl = `/balance-groups/${accountBalanceGroupId}/balance-views`;
    return this.http.get(`${this.baseUrl}${balViewsUrl}`);
  }

  private getBalanceSegments(accountBalanceViewId: number | string): Observable<any> {
    let balSegUrl = `/balance-views/${accountBalanceViewId}/balance-segments`;
    return this.http.get(`${this.baseUrl}${balSegUrl}`);
  }

【问题讨论】:

    标签: angularjs angular rxjs migration observable


    【解决方案1】:
    1. 您可以使用forkJoin 代替mergeMap + flatMap(它们是同义词)来并行触发多个请求。
    2. 鉴于请求的性质,您可能必须使用多个嵌套的 forkJoin
    3. 虽然我已经使用 Array#reduce 转换了 loadash sumBy,但我留下了不完整的 sort 供您执行。

    试试下面的

    getBalanceGroups(): Observable<any> {
      return this.http.get(`/accounts/${accountId}/balance-groups`, { params: stateParams }).pipe(
        switchMap((response: any) =>
          forkJoin(
            response.data.map((item: any) => 
              getBalanceViews(item.accountBalanceGroupId, item).pipe(
                map((balanceViewData: any) => ({
                  ...item,
                  balanceViews: balanceViewData.sort()            // <-- incomplete
                })),
                switchMap((item: any) => 
                  forkJoin(
                    item.balanceViews.map((view: any) =>
                      getBalanceSegments(view.accountBalanceGroupId).pipe(
                        map((balanceSegmentData: any) => ({
                          ...item,
                          balanceSegments: balanceSegmentData,
                          totalBalance: view.balanceSegments.reduce((acc, curr) => acc += curr['balance'], 0)
                        }))
                      )
                    )
                  )
                )
              )
            )
          )
        ),
        map((response: any) => ({
          ...response,
          response.data: response.data.sort()                      // <-- incomplete
        })),
        catchError((error: any) => {
          console.error('Unable to return balance group for the balanceChiclet');
          return of(error);
        })
      );
    }
    

    【讨论】:

    • 感谢您花时间解释这一点。这确实有助于解释 RXJS 过程。我将尝试这种方法,如果它对我有用,这将使我更好地理解如何重构未来的服务。我需要更新数百个类似的东西。遵循随处发布的 rxjs 简单教程很容易,但将其应用于真正的应用程序 angularJs 重构并不容易。再次感谢。
    • 已确认。这个答案有助于解决我遇到的问题。我不得不更改一些位以适应我的真实模型,但这绝对有帮助。现在是时候解决下一个问题了!
    • 我同意在开始时让 RxJS 运算符适应现实世界的问题会非常耗时。但它变得更容易了。您可以将运算符拆分为小块,并使用模拟数据对其进行处理以掌握行为。我会说 Stackblitz 对于快速的小型会议非常方便。
    猜你喜欢
    • 2019-01-23
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 2016-12-09
    • 2016-04-11
    相关资源
    最近更新 更多