【问题标题】:rxjs with multiple forkjoin when doing http requests执行 http 请求时具有多个 forkjoin 的 rxjs
【发布时间】:2017-05-03 09:51:28
【问题描述】:

我正在做一些 http 请求并使用 rxjs 来成功通知结果:

  getReportings(departmentId: number): Observable<any> {
        return Observable.forkJoin(
            this.http.get('/api/members/' + departmentId).map(res => res.json()),
            this.http.get('/api/reports/' + departmentId).map(res => res.json())
        );
    }

当两个 http 请求都完成后,我希望在 getReportings 方法中迭代报告数组,读取一些值,然后为每个报告再次使用这些值创建一个新的 http 请求。

总而言之,我有 2 个(成员/报告)+ appr。 4 到 8 个(其他)请求。

当所有 appr.完成了 6 到 8 个请求我想在成功的处理程序中获取前 6 到 8 个请求的所有数据。

如何使用 rxjs 做到这一点?

更新

当用户 olsn 询问更多详细信息时,我现在了解他的顾虑,我在这里放了更多数据(伪代码)6 到 8 个请求应该是什么样子:

getReportings(departmentId: number): Observable<any> {
    return Observable.forkJoin(
        this.http.get('/api/members/' + departmentId).map(res => res.json()),
        this.http.get('/api/reports/' + departmentId).map(res => res.json())
    ).switchMap((result: [any[], any[]]) => {
        let members: any[] = result[0];
        let reports: any[] = result[1];
        let allNewStreams: Observable<any>[] = [
            Observable.of(members),
            Observable.of(reports)
        ]; 

        for(let report of reports)
        {
            allNewStreams.push(
this.http.get(report.url + ?key1=report.name1?).map(res => res.json()));
        }


        return Observable.forkJoin(allNewStreams); // will contain members, reports + 4-6 other results in an array [members[], reports[], ...other stuff]
    });
}

【问题讨论】:

    标签: angular rxjs angular2-http reactive-extensions-js


    【解决方案1】:

    您可以使用switchMap 扩展您的流,如下所示:

    getReportings(departmentId: number): Observable<any> {
        return Observable.forkJoin(
            this.http.get('/api/members/' + departmentId).map(res => res.json()),
            this.http.get('/api/reports/' + departmentId).map(res => res.json())
        ).switchMap((result: [any[], any[]]) => {
            let members: any[] = result[0];
            let reports: any[] = result[1];
            let allNewStreams: Observable<any>[] = [
                Observable.of(members),
                Observable.of(reports)
            ];
            // do your stuff and push new streams to array...
            if (foo) { // for each additional request
                let reportId: string | number = reports[0].id; // or however you retrieve the reportId
                allNewStreams.push(
                    this.http.get('some/api/ + bar)
                        .map(res => res.json())
                        .map(data => ({reportId, data})); // so your final object will look like this: {reportId: "d38f68989af87d987f8", data: {...}}
                );
            }
    
            return Observable.forkJoin(allNewStreams); // will contain members, reports + 4-6 other results in an array [members[], reports[], ...other stuff]
        });
    }
    

    应该这样做,它更像是一种 "old-style-logic-hammer" 方法 - 如果您正在寻找它:可能有一种更优雅的方法可以通过使用来解决这个问题其他运算符,但如果不了解完整数据和所有逻辑,这很难说。

    【讨论】:

    • 谢谢!变量的含义真的可以提供更好的技术解决方案吗?没有更多关于 http 请求的逻辑。当 tge 单个客户端服务调用获取他订阅的所有 http 请求的数据时,逻辑就开始了。您缺少哪些“完整数据”?
    • 问题是:如何确定其他 4-6 个请求,我的理解是,它们依赖于 member+reports 请求中的某些数据并且可能会或可能不会被调用 - 这可能是基于在报告的数量上......它可能基于报告中的一些标志......或......或......ect......取决于可以使用不同的rxjs运算符 - 在任何情况下if /else -way 应该不会少。
    • 刚刚测试了代码,它可以工作。但随着事情的发展,我意识到我仍然有一个问题。所有 4-8 个请求“可能”在响应中以随机顺序到达。我不想离开 rxjs 作者的大脑 ;-) 关于我的伪代码,是否可以在 http 请求完成后为 4-8 个请求中的每一个传递一个 report_Id?我希望将返回数据与每个报告关联起来。假设每个报告报告都有一个 id,而不是为每个 report.url 请求返回一个数据数组,而是返回一个带有 report_Id 和返回数据的对象:-)
    • 当然,只需添加一个额外的 .map(...) - 订阅中的顺序不应该是随机的,无论执行时间如何,因为 forkjoin 只会在所有请求完成后传播数据 -它们的顺序与输入数组的顺序相同。
    • 我同意,当我在 component.ts 中获得成功的响应及其数组时,allNewStreams 及其可观察项目的顺序是相同的,但我不知道这些东西是如何在我的报告服务中映射的.ts 因此我最终需要参考 :-) 你能告诉我更多请你如何使用 .map() 方法将每个 report.id 映射到调用 4-8 请求吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多