组合多个 FirebaseListObservables [英] Combining multiple FirebaseListObservables
问题描述
const placeId = this.getPlaceId();
this.af.database.list(`placeUsers/${placeId}`).subscribe((userKeys) => {
for (let index = 0; index < userKeys.length; index++) {
let userKey = userKeys[index];
this.af.database.list(`userDevices/${userKey.$key}`).subscribe((deviceKeys) => {
for (let index = 0; index < deviceKeys.length; index++) {
let deviceKey = deviceKeys[index];
this.af.database.object(`devices/${deviceKey.$key}`).subscribe((device) => {
console.log(device);
// Device received.
});
}
});
}
});
我目前正在尝试向所有关注某个地点的用户发送通知.目前的流程是这样的:
I'm currently trying to send notifications to all my users that are following a place. The current flow goes like this:
- 获取属于某个地点的用户(placeUsers 节点)
- 获取属于用户的设备密钥(userDevices 节点)
- 从 deviceKeys(设备节点)获取设备
我想知道是否有办法将所有这些调用组合成一个可观察的调用.
I was wondering if there was a way to combine all these calls into a single observable call.
我目前的问题是,我无法知道所有这些请求何时完成.我研究了 RxJs,它可以让我将所有这些可观察对象结合起来.但是我还没有找到一个很好的解决方案来说明如何使用四个节点来做到这一点.
What my current problem is, is that i am unable to know when all of these requests are done. I've looked into RxJs, which would allow me to combine all these observables. But i haven't found a good solution on how to do it with four nodes.
推荐答案
您可以使用 concatMap
和 forkJoin
来组成一个发射设备的 observable.这个组合的 observable 将发出单个设备数组,然后将完成(因为 first
运算符用于仅获取第一个发出的列表或对象):
You can use concatMap
and forkJoin
to compose an observable that emits the devices. This composed observable will emit a single array of devices and will then complete (as the first
operator is used to take only the first emitted list or object):
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/concatMap';
import 'rxjs/add/operator/first';
import 'rxjs/add/operator/forkJoin';
this.af.database
.list(`placeUsers/${placeId}`)
.first()
.concatMap(userKeys => {
let observables = userKeys.map(userKey => this.af.database
.list(`userDevices/${userKey.$key}`)
.first()
);
return observables.length ?
Observable.forkJoin(...observables, (...lists) => [].concat(...lists)) :
Observable.of([])
})
.concatMap(deviceKeys => {
let observables = deviceKeys.map(deviceKeys => this.af.database
.object(`devices/${deviceKey.$key}`)
.first()
);
return observables.length ?
Observable.forkJoin(...observables) :
Observable.of([])
})
.subscribe(devices => console.log(devices));
如果你想要一个不完整的 observable 并且在一个地方的用户或他们的设备发生变化时发出一个地方的设备,请使用 switchMap
而不是 concatMap
,combineLatest
而不是 forkJoin
并删除 first
运算符:
If you want an observable that does not complete and emits the devices for a place whenever the users for a places or their devices change, use switchMap
instead of concatMap
, combineLatest
instead of forkJoin
and remove the first
operators:
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/combineLatest';
import 'rxjs/add/operator/switchMap';
this.af.database
.list(`placeUsers/${placeId}`)
.switchMap(userKeys => {
let observables = userKeys.map(userKey => this.af.database
.list(`userDevices/${userKey.$key}`)
);
return observables.length ?
Observable.combineLatest(...observables, (...lists) => [].concat(...lists)) :
Observable.of([])
})
.switchMap(deviceKeys => {
let observables = deviceKeys.map(deviceKeys => this.af.database
.object(`devices/${deviceKey.$key}`)
);
return observables.length ?
Observable.combineLatest(...observables) :
Observable.of([])
})
.subscribe(devices => console.log(devices));
这篇关于组合多个 FirebaseListObservables的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!