【问题标题】:Fork join two firebase observablesFork 加入两个 firebase observables
【发布时间】:2017-01-12 04:19:00
【问题描述】:

我正在使用 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 游览对象,我会得到一个“FirebaseObjectObservable”数组。

我必须遍历所有 FirebaseObjectObservable,才能获取实际数据。

我想知道是否可以 forkJoin 所有 observables 并将输出作为具有单个订阅函数的数组获取。

这是一个正确的方法。

我知道我可以在所有观察者数组上做一个异步管道,但我想在控制器中获取数据,然后在它显示在视图中之前进行一些处理,所以异步管道真的不是最好的解决方案我。

【问题讨论】:

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


    【解决方案1】:

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

    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 将不会发出值,直到所有内部 observable 都完成 - 也就是说,直到每个城市的游览都被查找完。这可能会影响 感知 性能 - 如果在查找 /tours/${tour.$key}/tours 中的信息之前可以显示 /cities/${cityId}/tours 中的信息,您将无法显示它。同样,您将无法在结果到达时显示该城市的游览。

    使用forkJoin 使处理实现更简单,但它可能会使UI 感觉更慢。 (但是,您可能不希望对 UI 进行零碎更新。)

    请注意,如果您确实需要在视图中显示每个城市的游览之前对其进行一些处理,您也许可以对问题代码中的 observables 执行上述处理。例如,使用您的 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 管道,它会接收您处理过的游览。

    【讨论】:

    • 这行得通,但我想知道我的想法是否正确,如果我有很多记录,这会使系统变慢吗?
    • 我刚刚阅读了您的评论。明天我会在答案中添加一些性能说明;来晚了。
    • 不用担心,非常感谢 :)
    • 更新了答案:forkJoin 是否是正确的方法。
    • 有没有使用 joinfork 的方法没有 complete / first() ?我有类似的问题,但需要保持第一个连接:stackoverflow.com/questions/41785252/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 2018-05-31
    • 2013-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多