forkJoin的成功回调未得到调用

问题描述 投票:0回答:4

我必须在我的angular应用程序中进行两个并行的API调用,并且每个组件中的数据都将使用。以下是我的服务和组件文件代码。我使用forkJoin进行并行调用和处理。因为根据我的理解,forkJoin确保在两个API调用均成功时将调用成功回调。

运行时,我可以看到在每个服务中都调用了成功回调,但是在组件文件中却没有。

api.services.ts

$getRequestById(id: string): Subject<any> {
    const data_subject = new Subject<any>();
    this.$http.get(API_URL + '/' + id).subscribe(
      (dto) => data_subject.next(new Request(dto)), // THIS IS GETTING EXECUTED
      (error) => data_subject.error(error)
    );
    return data_subject;
  }

  $getAllRequestsForId(id: string): Subject<any> {
    const data_subject = new Subject<any>();

    this.$http.get(API_URL + '?request_id=' + id).subscribe(
      (dto) => data_subject.next(dto.map(i => new Request(i))),
      (error) => data_subject.error(error)
    );

    return data_subject;
  }

在我的组件文件中,

home.component.ts

const request = this.service.$getRequestById(this.id);
const allRequests = this.service.$getAllRequestsForId(this.id);

forkJoin([request, allRequests])
 .subscribe(
    (response) => this.setResponse(response), // THIS LINE IS NOT GETTING CALLED.
    (error) => this.notification.error('Error occured while fetching request details! Please try again.')
 );

但是,如果我在任何组件中独立运行此API调用,如下所示,它将正常工作而没有任何问题。

this.service.$getRequestById(this.id).subscribe(
(response) => this.setResponse(response), // THIS GETS EXECUTED 
(error) => this.notification.error("An error occured")
)

我正在应用程序的其他部分独立使用这些服务,没有任何问题,但是当与forkJoin结合使用时,不会调用成功回调。知道如何解决在forkJoin和独立调用中均有效的问题吗?

angular rxjs observable angular-httpclient angular2-observables
4个回答
2
投票

我会说,使用RxJS Subject会使调用不必要地变得复杂。您可以从HttpClient返回可观察对象,并使用forkJoin对其进行组合。

forkJoin docs

等待Observables完成,然后合并它们的最后一个值发出。

因此,如果Subject之一未完成,则forkJoin将不会发出响应。如果希望在订阅之前从可观察对象修改响应,则可以使用RxJS mapmap运算符。您可能不需要此处的catchError,因为您没有修改HTTP请求中的错误。

尝试以下操作

服务

catchError

控制器

catchError

更新:import { pipe } from 'rxjs'; import { map } from 'rxjs/operators'; $getRequestById(id: string): Observable<any> { return this.$http.get(API_URL + '/' + id).pipe( map(dto => new Request(dto)) ); } $getAllRequestsForId(id: string): Observable<any> { return this.$http.get(API_URL + '?request_id=' + id).pipe( map(response => response.map(item => new Request(i))) // <-- inner `map` is array method, outer `map` is RxJS operator ); }

使用const request = this.service.$getRequestById(this.id); const allRequests = this.service.$getAllRequestsForId(this.id); forkJoin([request, allRequests]).subscribe( (response) => this.setResponse(response), (error) => this.notification.error('Error occured while fetching request details! Please try again.') ); 要记住的最重要的事情是返回一个可观察的对象。您可以使用RxJS catchError发出错误并完成。或者,您可以使用RxJS catchError返回一个可观察的对象。

throwError

1
投票

您的代码应为

throwError

home.component.ts

of

0
投票

未调用API,因为您已经通过使用of消耗了API,因此请删除订阅并像这样再次尝试

api.services.ts] >>

import { pipe, throwError, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

// throwing error using `throwError`
$getRequestById(id: string): Observable<any> {
  return this.$http.get(API_URL + '/' + id).pipe(
    map(dto => new Request(dto)),
    catchError(error => throwError('Ran into an error: ', error))       
  );
}

// throwing error using `of`
$getRequestById(id: string): Observable<any> {
  return this.$http.get(API_URL + '/' + id).pipe(
    map(dto => new Request(dto)),
    catchError(error => of('Ran into an error: ', error))               
  );
}

home.component.ts

$getRequestById(id: string): Observable<any> {
    return this.$http.get(API_URL + '/' + id).pipe(map(
      (dto) => new Request(dto)), // THIS IS GETTING EXECUTED
      (catchError) => throwError(err)
    );
  }

  $getAllRequestsForId(id: string): Observable<any> {
    return this.$http.get(API_URL + '?request_id=' + id).pipe(map(
      (dto) => dto.map(i => new Request(i))),
      (catchError) => throwError(error)
    );
  }

0
投票

forkjoin仅在每个可观察到的源完成后才调用订阅回调。在您的服务功能中,您返回的主题从未完成,因此forkjoin将永远等待。

© www.soinside.com 2019 - 2024. All rights reserved.