如何切换映射3个可观察对象的流

时间:2020-04-08 20:57:51

标签: javascript angular typescript firebase rxjs

我必须将3个Observable流合并为一个。 我正在使用Angular和Firebase,这是应该如何工作的...

步骤1:我向Firebase发送查询并收到array。我将使用特定属性中的 id 来查询步骤2 的其他内容。

步骤2:我使用步骤1 中的 ID 从另一个集合中获取数据,为此,我将收到另一个array。在此数组中,我还有一个 ID ,用于第3步

第3步:我需要使用第2步中提供的 ID 从数据库中获取对象。

为了使此工作正常进行,我正在使用switchMap(),但问题是由于该方法,我得到了VOID

请帮助!

更新:我更改了原始代码。有了这个,我可以看到console.log,但是当我订阅时,我什么也没得到。

getPanic() {
  this.panicInfo = this.panicService.getPanic(this.checkID)
    .pipe(
      switchMap(panicSnaps => {
        const requests = panicSnaps.map(panicSnap => {
          const panicObj = {id: panicSnap.payload.doc.id, ...panicSnap.payload.doc.data() as any};
          return this.panicService.getActions(panicObj.id)
            .pipe(
              tap({ complete: () => console.log('completed')}),
              map(data => {
                panicObj.actions = data;
                console.log(panicObj);
                return panicObj;
              })
            );
        });
        return forkJoin(requests);
      }),
    )
    .subscribe();
}

2 个答案:

答案 0 :(得分:0)

最好将流分开,这样您就可以看到问题出在哪里。

getActionUsers(actionSnaps) {
  const actions = actionSnaps.map(actionSnap => {
    const actionsObj: PanicActions = {...actionSnap};
    // need to return inside map
    return this.userService.getUser(actionsObj.executor).pipe( 
      map(userSNAP => ({...actionsObj, ...userSNAP})) // combine only action and user here
    );
  });
  // need to combine and return (deal with empty)
  return actions.length ? combineLatest(...actions) : of([]);
}

getPanicActions(panicData) {
  const panic = panicData.map(snaps => {
    const panicObj: Panic = {...snaps.payload.doc.data()};
    return this.panicService.getActions(panicObj.id).pipe(
      switchMap(actionSnaps => this.getActionUsers(actionSnaps).pipe(
        map(res => ({...panicObj, ...res})) // add panicObj here
      ))
    );
  });
  // forkJoin only works on observables that complete, use combineLatest when they don't, also need to deal with empty
  return panic.length ? combineLatest(...panic) : of([]);
}


getPanic() {
  this.panicService.getPanic(this.checkID).pipe( 
    switchMap(panicData => this.getPanicActions(panicData))
  ).subscribe(data => {
    // The panicInfo is of type 'Panic' but I get a TS Lint error that says:
    // Type 'void[]' is missing the following properties from type 'Panic': id, checkId, city, geolocation, and 10 more
    this.panicInfo = data;
  });
}

答案 1 :(得分:0)

测试此代码:

getPanic() {
  this.panicService.getPanic(this.checkID)
    .pipe(
      switchMap((panicData: any[]) => forkJoin(
        ...panicData.map(snaps => {
          const panicObj = { ...snaps.payload.doc.data() };

          return this.panicService.getActions(panicObj.id).pipe(
            switchMap((actionSnaps: any[]) => forkJoin(
              ...actionSnaps.map(actionSnap => {
                const actionsObj: any = { ...actionSnap };

                return this.userService.getUser(actionsObj.executor).pipe(
                  map(userSNAP => ({ ...panicObj, ...actionsObj, ...userSNAP })),
                );
              }),
            )),
          );
        }),
      )),
    )
    .subscribe(data => {
      // The panicInfo is of type 'Panic' but I get a TS Lint error that says:
      // Type 'void[]' is missing the following properties from type 'Panic': id, checkId, city, geolocation, and 10 more
      this.panicInfo = data;
    });

我在stackblitz上的示例

我不知道您在请求中收到什么数据。