I am trying to populate an array in my component called processes
which is an array of process
. Each process
also has a list of tasks
.
So currently, I am working with two api calls which are:
/processes
and
/process/{processId}/tasks
I use /processes
to get all the processes and initially populate the processes
array. Then I use the process id of each process
to call the second API to get the tasks of that process.
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
. Any ideas on how I can go about approaching this issue?
concat() which will handle each observable in sequence.
forkJoin is an operator that takes any number of input observables which can be passed either as an array or a dictionary of input observables. If no input observables are provided (e.g. an empty array is passed), then the resulting stream will complete immediately.
The forkJoin observable now takes a dictionary of sources: Moreover, there is one deprecation — forkJoin(a, b, c, d) should no longer be used; Instead, pass an array such as forkJoin([a, b, c, d]) .
“If any input observable errors at some point, forkJoin will error as well and all other observables will be immediately unsubscribed.”
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.
As @Juan Mendes mentioned, Observable.forkJoin
will return an array of tasks that match the index of each process in your processes array. 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With