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

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

Step 1: I send a query to Firebase and receive an array. I will use the id from a specific property to query something else for the Step 2.

Step 2: I use the ID from Step 1 to get data from another collection, for this I'll receive another array. In this array, I have another ID that I need for Step 3.

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

In order to get this working, I'm using switchMap() but the problem is that I'm getting VOID as result of the method.

请帮助!

getPanic() {
    this.panicService.getPanic(this.checkID)
        .pipe(
            switchMap(panicData => {
                const panic = panicData.map(snaps => {
                    const panicObj: Panic = {...snaps.payload.doc.data()};
                    return this.panicService.getActions(panicObj.id).pipe(map(actionSnaps => {
                        const actions = actionSnaps.map(actionSnap => {
                            const actionsObj: PanicActions = {...actionSnap};
                            const user = this.userService.getUser(actionsObj.executor).pipe(map(userSNAP => {
                                return {...panicObj, ...actionsObj, ...userSNAP};
                            }));
                        });
                    }));
                });
                return forkJoin(panic);
            })
        )
        .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;
        });
}

评论
  • 沫沫浅言
    沫沫浅言 回复

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

    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;
      });
    }
    
  • 梅Oo
    梅Oo 回复

    测试此代码:

    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;
        });
    

    my example on stackblitz

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