简体   繁体   English

具有for循环的Observable.forkJoin

[英]Observable.forkJoin with a for loop

I am trying to populate an array in my component called processes which is an array of process . 我正在尝试在我的组件中填充一个名为processes的数组,这是一个process数组。 Each process also has a list of tasks . 每个process还有一个tasks列表。

So currently, I am working with two api calls which are: 所以目前,我正在使用两个api调用:

/processes and /process/{processId}/tasks /processes/process/{processId}/tasks

I use /processes to get all the processes and initially populate the processes array. 我使用/processes来获取所有进程并最初填充processes数组。 Then I use the process id of each process to call the second API to get the tasks of that process. 然后我使用每个process的进程ID来调用第二个API来获取该进程的任务。

Currently, my code looks something like this: 目前,我的代码看起来像这样:

this.processes.forEach((process, index) => {
    myService.getTasks().subscribe((tasks) => {
        process.tasks = tasks;
    })
})

I understand that I can create an array of observables, and use Observable.forkJoin() to wait for all these async calls to finish but I want to be able to define the subscribe callback function for each of the calls since I need a reference to the process . 我知道我可以创建一个observable数组,并使用Observable.forkJoin()等待所有这些异步调用完成但我希望能够为每个调用定义subscribe回调函数,因为我需要一个引用这个process Any ideas on how I can go about approaching this issue? 关于如何处理这个问题的任何想法?

Using the for loop to make multiple HTTP requests, and then subscribe to all of them separately should be avoided in order not to have many Observable connections opened. 使用for循环来发出多个HTTP请求,然后分别订阅所有这些请求,以避免打开很多Observable连接。

As @Juan Mendes mentioned, Observable.forkJoin will return an array of tasks that match the index of each process in your processes array. 正如@Juan Mendes所提到的, Observable.forkJoin将返回一个与进程数组中每个进程的索引相匹配的任务数组。 You can also assign tasks to each process as they arrive as follows: 您还可以在到达时为每个流程分配任务,如下所示:

getTasksForEachProcess(): Observable<any> {

    let tasksObservables = this.processes.map(process, processIdx) => {
        return myService.getTasks(process)
            .map(tasks => {
                this.processes[processIdx].tasks = tasks; // assign tasks to each process as they arrive
                return tasks;
             })
            .catch((error: any) => {
                console.error('Error loading tasks for process: ' + process, 'Error: ', error);
                return Observable.of(null); // In case error occurs, we need to return Observable, so the stream can continue
            });
    });

    return Observable.forkJoin(tasksObservables);
};

this.getTasksForEachProcess().subscribe(
    tasksArray => {
        console.log(tasksArray); // [[Task], [Task], [Task]];
        // In case error occurred e.g. for the process at position 1,
        // Output will be: [[Task], null, [Task]];

        // If you want to assign tasks to each process after all calls are finished:
        tasksArray.forEach((tasks, i) => this.processes[i].tasks = tasksArray[i]);
    }
);

Please also take a look at this post: Send multiple asynchronous HTTP GET requests 另请看这篇文章: 发送多个异步HTTP GET请求

Thanks to Seid Mehmedovic for great explanation but it looks like code missing one round bracket near map. 感谢Seid Mehmedovic提供了很好的解释,但看起来代码在地图附近丢失了一个圆括号。 For me it worked as follows: 对我来说它的工作原理如下:

getTasksForEachProcess(): Observable<any> {

    let tasksObservables = this.processes.map((process, processIdx) => {
        return myService.getTasks(process)
            .map(tasks => {
                this.processes[processIdx].tasks = tasks; // assign tasks to each process as they arrive
                return tasks;
             })
            .catch((error: any) => {
                console.error('Error loading tasks for process: ' + process, 'Error: ', error);
                return Observable.of(null); // In case error occurs, we need to return Observable, so the stream can continue
            });
    });

    return Observable.forkJoin(tasksObservables);
};

this.getTasksForEachProcess().subscribe(
    tasksArray => {
        console.log(tasksArray); // [[Task], [Task], [Task]];
        // In case error occurred e.g. for the process at position 1,
        // Output will be: [[Task], null, [Task]];

        // If you want to assign tasks to each process after all calls are finished:
        tasksArray.forEach((tasks, i) => this.processes[i].tasks = tasksArray[i]);
    }
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM