Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
561 views
in Technique[技术] by (71.8m points)

javascript - Observable.forkJoin with a for loop

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...