angularfire2 rxjs使用动态更新来加入两个表中的observable

时间:2017-08-06 00:31:47

标签: angular rxjs observable angularfire2 ngrx

所以我有两张桌子。其中一个是我的用户存储块 另一个存储这些块的数据。

我正在尝试正确组合这些,所以在我的组件中,我根据dataID得到了一个包含数据的块列表

- user
    - blocks
        - block1
            - blockSize
            - blockOptions
                - dataID
        - ...

- data
  - dataId1
      - stuff ...
  - ...

使用以下代码我得到我的块和数据,但数据节点仍然是FirebaseObervable。所以我必须在我的哑组件中使用async。我要问的是如何正确组合这些,所以我只需要使用异步管道并将数据推送到子组件。虽然没有失去动态变化。

return this.db.list(`/user/${this.userId}/blocks`).switchMap((blocks:Block[]) => {
  let blockData$ = blocks.map(block => {        
      return this.db.object(`/data/${block.blockOptions.dataID}`)
  });
  return Observable.combineLatest(blockData$,blocks, (bData,block) => {
    block.data = bData;
    return blocks;
  });
})

模板示例

//what I want to happen
*ngFor="let block of blocks | async">
<dumb-component [blockData] = "block.data"></dumb-component>

//what I have to do now
*ngFor="let block of blocks | async">
<dumb-component [blockData] = "block.data | async"></dumb-component>

先谢谢,我觉得非常接近正确方向的任何推动都会受到赞赏

1 个答案:

答案 0 :(得分:2)

你很亲密。它只是需要进行一些更改的Observable.combineLatest调用:

return this.db.list(`/user/${this.userId}/blocks`)
  .switchMap((blocks: Block[]) => {
    let arrayOf$ = blocks.map(block => {
      return this.db.object(`/data/${block.blockOptions.dataID}`)
    });
    return Observable.combineLatest(arrayOf$, (...arrayOfData) => {
      blocks.forEach((block, index) => {
        block.data = arrayOfData[index];
      });
      return blocks;
    });
  });

您对blocks.map的调用会返回一组可观察对象,因此您要使用的combineLatest签名为this one

export function combineLatest<T, R>(
  array: ObservableInput<T>[],
  project: (...values: Array<T>) => R,
  scheduler?: IScheduler
): Observable<R>;

你传递了一个observable数组,它用结果调用你的项目函数。只需将它们收集到一个数组中,迭代blocks,然后在适当的索引处分配结果。

如果您正在使用ngrxOnPush更改检测,则应确保不对块数组或块本身进行突变。为了避免突变,combineLatest调用将是这样的:

return Observable.combineLatest(arrayOf$, (...arrayOfData) => {
  return blocks.map((block, index) => {
    const data = arrayOfData[index];
    if (block.data !== data) {
        // If the block has no data or if the data has changed,
        // copy the block to avoid mutating it.
        return Object.assign({}, block, { data });
    }
    return block;
  }
});