【问题标题】:Rxjs switchMap + toArrayRxjs switchMap + toArray
【发布时间】:2020-07-03 13:23:58
【问题描述】:

我遇到了 rxjs 的问题。

我有一个应该这样做的函数:

  • 拥有组 ID 列表。在示例中:of(['1', '2'])
  • 为每个人获取聊天列表
  • 返回合并的聊天列表

当执行到 toArray 时什么都没有发生,没有结果。

代码

  get chats$(): Observable<Chat[]> {
    return of(['1', '2']).pipe(
      filter(groupIds => !!groupIds && groupIds.length > 0),
      switchMap(groupIds => groupIds),
      switchMap(groupId => getGroupChats(groupId)), // fetch list of chats for the group id
      toArray(),
      map(doubleList => {
        return ([] as Chat[]).concat(...doubleList); // merge chat lists
      })
    );
  }

我也试过这个:

get chats$(): Observable<Chat[]> {
    return of(['1', '2']).pipe(
      filter(groupIds => !!groupIds && groupIds.length > 0),
      map(groupIds =>
        groupIds.map(groupId => getGroupChats(groupId))
      ),
      switchMap(chatList$ =>
        forkJoin(chatList$).pipe(
          map(doubleList => {
            return ([] as Chat[]).concat(...doubleList);
          })
        )
      )
    );
}

测试

测试响应为:Error: Timeout - Async callback was not invoked within 5000ms

describe("WHEN: get chats$", () => {
  const CHAT_MOCK_1: Chat = {
    id: "1",
  };
  const CHAT_MOCK_2: Chat = {
    id: "2",
  };

  it("THEN: get chats$ should return chat list", (done) => {
    service.chats$
      .subscribe((data) => {
        expect(data.length).toEqual(2);
        expect(data[0]).toEqual(CHAT_MOCK_1);
        expect(data[1]).toEqual(CHAT_MOCK_2);
        done();
      })
      .unsubscribe();
  });
});

【问题讨论】:

  • 我想知道您是否找到任何解决方案。
  • 刚刚发布!谢谢你提醒我:)

标签: angular typescript rxjs toarray switchmap


【解决方案1】:

这段代码sn-p将获取一个id数组,分别获取结果并收集到一个数组中

from([1,2,3,4])
  .pipe(
    mergeMap(a => of(a * 10)), // send request if you need hare or any observable
    toArray()
  ).subscribe(console.log);

【讨论】:

  • 谢谢,但我最初的 observable 的类型是 Observable>,我需要为该数组的每个元素获取数据
  • 没关系,您可以将上面的代码更改为从 (['1', '2', '3', '4']) 获取 Observable>。但你需要照顾乘法
  • 就像from([['1','2','3']]),就像of(['1', '2', '3'])。我的问题是处理乘法:D
【解决方案2】:

最后这就是我所做的(并且有效):

  • 使用普通的 Array.map 将我们的群组 ID 数组转换为可观察对象列表,每个可观察对象都包含该群组的聊天数组。
  • 使用forkJoin 获取生成的数组的每个可观察对象的最终发射值。

代码

get chats$(): Observable<Chat[]> {
    return this.groupsIds$.pipe(
        skipUntil(this._groupsLoaded$),
        switchMap((ids) => {
            const chatsList: Observable<Chat[]>[] = ids.map((id) =>
                this.getGroupChats$(id)
            );

            return forkJoin([...chatsList]).pipe(
                map((list) => ([] as Chat[]).concat(...list))
            );
        })
    )
}

我仍然对为什么它有效而不是以前的版本有一些疑问,如果有人能解释一下那就太好了。

作为结论:不要连接多个switchMap

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-14
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    相关资源
    最近更新 更多