angularfire2 rxjs 通过动态更新从两个表中加入 observable
angularfire2 rxjs join observables from two tables with dynamic updates
所以我有两张桌子。其中之一是我的用户,它存储块
另一个存储这些块的数据。
我正在尝试正确组合这些,因此在我的组件中,我根据 dataID
获得了一个块列表及其数据
- user
- blocks
- block1
- blockSize
- blockOptions
- dataID
- ...
- data
- dataId1
- stuff ...
- ...
使用以下代码我得到了我的块和数据,但数据节点仍然是一个 FirebaseObervable。所以我必须在我的哑组件中使用异步。我要问的是如何正确组合这些,以便我只需要使用异步管道并将数据推送到子组件。同时不丢失动态变化。
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>
提前致谢,我觉得非常接近任何正确方向的推动将不胜感激
你很接近。只有 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
returns 可观察值数组的调用,因此您要使用的 combineLatest 签名是 this one:
export function combineLatest<T, R>(
array: ObservableInput<T>[],
project: (...values: Array<T>) => R,
scheduler?: IScheduler
): Observable<R>;
您将一组可观察值传递给它,它会使用结果调用您的项目函数。只需将它们收集到一个数组中,迭代您的 blocks
,然后将结果分配到适当的索引处。
如果您正在使用 ngrx
或 OnPush
变化检测,您应该确保不会对块数组或块本身进行突变。为了避免突变,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;
}
});
所以我有两张桌子。其中之一是我的用户,它存储块 另一个存储这些块的数据。
我正在尝试正确组合这些,因此在我的组件中,我根据 dataID
获得了一个块列表及其数据- user
- blocks
- block1
- blockSize
- blockOptions
- dataID
- ...
- data
- dataId1
- stuff ...
- ...
使用以下代码我得到了我的块和数据,但数据节点仍然是一个 FirebaseObervable。所以我必须在我的哑组件中使用异步。我要问的是如何正确组合这些,以便我只需要使用异步管道并将数据推送到子组件。同时不丢失动态变化。
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>
提前致谢,我觉得非常接近任何正确方向的推动将不胜感激
你很接近。只有 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
returns 可观察值数组的调用,因此您要使用的 combineLatest 签名是 this one:
export function combineLatest<T, R>(
array: ObservableInput<T>[],
project: (...values: Array<T>) => R,
scheduler?: IScheduler
): Observable<R>;
您将一组可观察值传递给它,它会使用结果调用您的项目函数。只需将它们收集到一个数组中,迭代您的 blocks
,然后将结果分配到适当的索引处。
如果您正在使用 ngrx
或 OnPush
变化检测,您应该确保不会对块数组或块本身进行突变。为了避免突变,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;
}
});