Fork加入两个firebase observable

时间:2016-09-04 17:34:21

标签: angular firebase firebase-realtime-database observable rxjs5

我正在使用angular2fire。我正在查询并试图从一个城市获得所有的旅行。

getAllTours(cityId) {
    return this.af.database.list(`/cities/${cityId}/tours`)
        .map((tours): any => {
            tours.map((tour: any) => {
                tour.tour  = this.af.database.object(`/tours/${tour.$key}/tours`)
            });
            return tours;
        })
}

如果我在console.log中找到了tour对象,我会得到一个" FirebaseObjectObservable"的数组。

我必须循环遍历所有FirebaseObjectObservable,以获取实际数据。

我想知道我是否可以forkJoin所有的observable并将输出作为一个具有单个subscribe函数的数组。

这是一种正确的方法吗?

我知道我可以在所有观察者数组上执行异步管道,但我想在控制器内部获取数据,然后在视图中显示之前进行一些处理,因此异步管道实际上不是最佳解决方案我。

1 个答案:

答案 0 :(得分:7)

是的,forkJoin可用于获取内部可观察数据的数据:

getAllTours (cityId) {
    return this.af.database
        .list(`/cities/${cityId}/tours`)
        .mergeMap((tours) => {

            // The array of tours is going to be mapped to an observable,
            // so mergeMap is used.

            return Observable.forkJoin(

                // Map the tours to the array of observables that are to
                // be joined. Note that forkJoin requires the observables
                // to complete, so first is used.

                tours.map((tour) => this.af.database
                    .object(`/tours/${tour.$key}/tours`)
                    .first()
                ),

                // Use forkJoin's results selector to match up the result
                // values with the tours.

                (...values) => {
                    tours.forEach((tour, index) => { tour.tour = values[index]; });
                    return tours;
                }
            );
        });
}

是否使用forkJoin是正确的方法取决于您的要求。

使用上面的代码,getAllTours返回的observable将不会发出一个值,直到所有内部可观察量都已完成 - 也就是说,直到每个城市的游览被查找完毕。这可能会影响感知的效果 - 如果/cities/${cityId}/tours中的信息可以在/tours/${tour.$key}/tours中的信息被查找之前显示,则您将无法显示它。同样,当结果到达时,您将无法显示城市的游览。

使用forkJoin可以简化处理实现,但可能会让UI感觉更慢。 (但是,对UI的零碎更新可能是您不想要的。)

请注意,如果您需要在视图中显示每个城市的游览之前对其进行一些处理,您可以在问题的代码中对可观察对象执行所述处理。例如,使用您的getAllTours功能:

observable = getAllTours(someCityId);
observable.map((tours) => {

    tours.forEach((tour) => {

        // With your function, tour.tour is an observable, so map
        // could be used to process the values.

        tour.tour = tour.tour.map((value) => {

            // Do some processing here with the value.
        })

        // And, if you are not interested in dynamic updates, you could
        // call first.

        .first();
    });
    return tours;
});

然后,您可以在模板中使用async管道,它将接收您处理过的游览。