【问题标题】:How to switchMap a stream of 3 Observables如何切换映射 3 个 Observable 的流
【发布时间】:2020-07-21 09:48:23
【问题描述】:

我必须将 3 个 Observable 流合并为一个。 我正在使用 Angular 和 Firebase,这就是它的工作原理......

第 1 步:我向 Firebase 发送查询并收到 array。我将使用特定属性中的 id 来查询其他内容以获取 Step 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();
}

【问题讨论】:

  • firebase 提供数据流,而不是单次发射 observable,您是在寻找流还是一次性 observable?
  • 一次性 Observable 也可以。

标签: javascript angular typescript firebase rxjs


【解决方案1】:

拆分流是个好主意,这样您就可以看到哪里出错了。

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

【讨论】:

  • 嘿@bryan60 谢谢,但仍然没有工作。 :( 我不再收到以前的类型错误,但我什么也没得到。我尝试了 console.log 并没有任何反应。
  • 这表明您的内部流之一没有发出或您尚未切换到 combineLatest
  • 有办法测试吗?
  • 通过点击将日志记录添加到流中。看看是否有任何不发射
  • 嘿@bryan60 我什么都没试过 :( 我加了tap({ complete: () => console.log('completed')}) 没有日志
【解决方案2】:

测试这段代码:

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上的例子

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

【讨论】:

  • 给我回答请求的数据
  • 嘿@Chrus 我已经更改了代码。我现在可以在 switchmap 中看到 console.log,但是当我订阅时,我什么也得不到。
  • 嘿,具体在哪里,加入stackblitz
  • 嘿@Chris 我无法在 Stackblitz 上保存,它不允许我。但这里是要点。 gist.github.com/iconio/920dd4cf97852618061f833b6e237be3
  • 把这行return forkJoin(requests);改成这个return forkJoin(... requests);
猜你喜欢
  • 2018-03-05
  • 2022-01-08
  • 2021-12-28
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多