Rxjs 如何从失败的forkJoin请求中获取数据?

Rxjs 如何从失败的forkJoin请求中获取数据?,rxjs,ngrx,Rxjs,Ngrx,使用AngularRxjs和ngrx 我有一个调度4 API的操作,我正在执行以下操作=> @Effect() getAllModels$ = this.actions$.pipe( ofType<featureActions.GetAllModelsRequest>(featureActions.ActionTypes.GetAllModelsRequest), switchMap((action) => forkJoin([

使用
Angular
Rxjs
ngrx

我有一个调度4 API的操作,我正在执行以下操作=>

  @Effect()
  getAllModels$ = this.actions$.pipe(
    ofType<featureActions.GetAllModelsRequest>(featureActions.ActionTypes.GetAllModelsRequest),
    switchMap((action) =>
      forkJoin([
        this.dataService.GetAllModelFromServer(),
        this.dataService.GetAllModelFromHost(),
        this.dataService.GetAllModelFromCache(),
        this.dataService.GetAllModelFromPreference(),
      ]).pipe(
        map(
          ([server, host, cache, preference]) =>
            new featureActions.GetAllModelsSuccess({
              //...
            })
        ),
        catchError((error: HttpErrorResponse) => {
          return of(new featureActions.GetAllModelsFailed({ error: error.message }));
        })
      )
    )
  );
@Effect()
getAllModels$=此.actions$.pipe(
类型(featureActions.ActionTypes.GetAllModelsRequest),
开关映射((操作)=>
分叉连接([
this.dataService.GetAllModelFromServer(),
this.dataService.GetAllModelFromHost(),
this.dataService.GetAllModelFromCache(),
this.dataService.GetAllModelFromPreference(),
]).烟斗(
地图(
([服务器、主机、缓存、首选项]=>
新功能Actions.GetAllModelsAccess({
//...
})
),
catchError((错误:HttpErrorResponse)=>{
返回(new featureActions.GetAllModelsFailed({error:error.message}));
})
)
)
);
问题是,当其中一个API失败时,一切都会失败,而我的行动也会失败。检索到的所有数据(在一个端点失败之前)都将丢失


有没有办法获取catchError中检索到的数据,或者唯一的解决方案是将api一个接一个地链接起来?

您可以编写自己的
forkJoin
实现。下面是一个源于原始()的简单示例:

导出函数forkJoin2(…args:any[]):可观察{ const resultSelector=popsresultselector(args); const{args:sources,key}=argsArgArrayOrObject(args); 如果(结果选择器){ //不推荐的路径。 返回forkJoinInternal(源、键).pipe(映射((值:any[])=>resultSelector!(…值)); } 返回内部(源、密钥); } 函数forkJoinInternal(源:ObservableInput[],键:string[]| null):可观察{ 返回新的可观察对象((订户)=>{ const len=sources.length; 如果(len==0){ subscriber.complete(); 返回; } 常量值=新数组(len); 设完成=0; 设发射=0; for(让sourceIndex=0;sourceIndex{ 如果(!hasValue){ hasValue=true; 发射++; } 值[sourceIndex]=值; }, 错误:(err)=>{return subscriber.error({error:err,values})}, 完成:()=>{ 已完成++; 如果(已完成===len | |!hasValue){ 如果(发射===len){ next(key?key.reduce((result,key,i)=>((result as any)[key]=values[i]),result),{}:值); } subscriber.complete(); } }, }) ); } }); } 请注意,发生错误时,您将返回错误以及以下值:


error:(err)=>{return subscriber.error({error:err,values})}

我在这里找到了这个解决方案:

@Effect()
getAllModels$=此.actions$.pipe(
类型(featureActions.ActionTypes.GetAllModelsRequest),
开关映射((操作)=>
分叉连接([
this.dataService.GetAllModelFromServer().pipe(catchError(()=>of({data:[]})),
this.dataService.GetAllModelFromHost().pipe(catchError(()=>of({data:[]})),
this.dataService.GetAllModelFromCache().pipe(catchError(()=>of({data:[]})),
this.dataService.GetAllModelFromPreference().pipe(catchError(()=>of({data:[]})),
]).烟斗(
地图(
([服务器、主机、缓存、首选项]=>
新功能Actions.GetAllModelsAccess({
//...
})
),
catchError((错误:HttpErrorResponse)=>{
返回(new featureActions.GetAllModelsFailed({error:error.message}));
})
)
)
);

你不能。除非您想编写自己的自定义“forkJoin”实现。i、 e.你可以调整这个:
export function forkJoin2(...args: any[]): Observable<any> {
  const resultSelector = popResultSelector(args);

  const { args: sources, keys } = argsArgArrayOrObject(args);

  if (resultSelector) {
    // deprecated path.
    return forkJoinInternal(sources, keys).pipe(map((values: any[]) => resultSelector!(...values)));
  }

  return forkJoinInternal(sources, keys);
}

function forkJoinInternal(sources: ObservableInput<any>[], keys: string[] | null): Observable<any> {
  return new Observable((subscriber) => {
    const len = sources.length;
    if (len === 0) {
      subscriber.complete();
      return;
    }
    const values = new Array(len);
    let completed = 0;
    let emitted = 0;
    for (let sourceIndex = 0; sourceIndex < len; sourceIndex++) {
      const source = innerFrom(sources[sourceIndex]);
      let hasValue = false;
      subscriber.add(
        source.subscribe({
          next: (value) => {
            if (!hasValue) {
              hasValue = true;
              emitted++;
            }
            values[sourceIndex] = value;
          },
          error: (err) => { return subscriber.error({ error: err, values }) },
          complete: () => {
            completed++;
            if (completed === len || !hasValue) {
              if (emitted === len) {
                subscriber.next(keys ? keys.reduce((result, key, i) => (((result as any)[key] = values[i]), result), {}) : values);
              }
              subscriber.complete();
            }
          },
        })
      );
    }
  });
}
  @Effect()
  getAllModels$ = this.actions$.pipe(
    ofType<featureActions.GetAllModelsRequest>(featureActions.ActionTypes.GetAllModelsRequest),
    switchMap((action) =>
      forkJoin([
        this.dataService.GetAllModelFromServer().pipe(catchError(() => of({ data: [] }))),
        this.dataService.GetAllModelFromHost().pipe(catchError(() => of({ data: [] }))),
        this.dataService.GetAllModelFromCache().pipe(catchError(() => of({ data: [] }))),
        this.dataService.GetAllModelFromPreference().pipe(catchError(() => of({ data: [] }))),
      ]).pipe(
        map(
          ([server, host, cache, preference]) =>
            new featureActions.GetAllModelsSuccess({
              //...
            })
        ),
        catchError((error: HttpErrorResponse) => {
          return of(new featureActions.GetAllModelsFailed({ error: error.message }));
        })
      )
    )
  );