Observable的订阅永远不会触发

时间:2019-08-01 15:48:16

标签: angular rxjs

在订阅我的Observable时,我面临一种奇怪的行为。 由于某些原因,从未调用console.log(item),并且控制台上也没有错误。

this.store$
.pipe(
  select(getRecentNotes),
  mergeAll(),
  groupBy(item => item.status.code),
  mergeMap(group => group.pipe(toArray())),
  toArray()
)
.subscribe((items)=> console.log('Grouped Items', items));

顺便说一句,如果我仅管道传输 select(getRecentNotes),那么它将正常工作,并且我得到的是这样的内容:

[
  {id: 1, note: "ABC", status: {code: 1, name: 'active'}},
  {id: 2, note: "DEF", status: {code: 1, name: 'active'}},
  {id: 3, note: "HIJ", status: {code: 2, name: 'hidden'}}
]

更有趣的是,以下将起作用:

// This will work
this.store$
.pipe(
  select(getRecentNotes),
  mergeAll()
)
.subscribe((items)=> console.log('Bunch of Items', items));

但是,如果我添加了另一个运算符,例如toArray(),它将停止工作。

// This will not work
this.store$
.pipe(
  select(getRecentNotes),
  mergeAll(),
  toArray()
)
.subscribe((items)=> console.log('All items', items));

有没有我遗漏的隐藏规则? 我试图使用一个简单的Observable.from([])在StackBlitz上重现该问题,但一切似乎都可以正常工作。

更新1: 我在管道中添加了其他一些运算符,它们可以完成操作(例如打印到控制台)。但是.subscribe中的代码没有被调用

this.store$
.pipe(
  select(getRecentNotes),
  mergeAll(),
  tap((item)=> {console.log(item)}),   // <--- This is printed to the console
  reduce((acc, item)=> {
  console.log(acc);                    // <-- This is printed to the console
  console.log(item);
  return acc.push(item);
  },[]) 
)
.subscribe((items)=> console.log('All items', items));

1 个答案:

答案 0 :(得分:1)

正如@AnjilDhamala在评论中提到的那样,toArray之类的运算符直到流完成才执行。您的商店$可观察的价格保持开放状态,以便toArray运算符永远不会发出结果。

似乎您的目标是返回由代码分块的数组的数组?

简单的解决方法是在take(1)操作员调用之后添加select。这应该导致最后一个toArray返回一个数组数组。

但是,如果我的假设是正确的,那么所有这些可能都是不必要的。看起来使用所有这些rxjs运算符似乎是干净的,但是您要完成的工作的意图还很不清楚。在select之后,您可以使用一个函数来调用map,该函数将使用普通的旧JavaScript将您的数组分块。

this.store$
.pipe(
  select(getRecentNotes),
  map(x => chunkBy(x, x => x.status.code))
).subscribe((items)=> console.log('All items', items));

function chunkBy<T>(ary: T[], chunkKeySelector: (item: T) => any) {
  const result: T[][] = [];
  const indexMap = new Map<any, number>();

  for (let value of ary) {
    const key = chunkKeySelector(value);
    (indexMap.has(key)) 
      ? result[indexMap.get(key)].push(value)
      : indexMap.set(key, result.push([value]) - 1);
  }
  return result;
}