Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJs Angular 7 HttpClient multiple POST with forkJoin remove second subscribe?

I am creating a Work Item object with linked child Task objects. My function (createWorkItemAndChildren) takes two parameters, the workItem, and an array of Task objects. I want my function to return an array of all ids that are created (work item and tasks).

I have to have the parent ID back from one http POST call (workItemService.createWorkItem) before I can then create the child tasks which use another http POST method on the same service.

I now have the forkJoin in createChildWorkItems returning all of the child ids at once.

How do I refactor this so that there is only one subscribe, and to return the array with parent and child ids together?

  createChildWorkItems(parentId, tasks: Task[]): Observable<any> {
    return <Observable<number>> forkJoin(
      tasks.map(task => <Observable<number>> this.workItemService.createChildWorkItem(parentId, task))
    ).pipe(zip());

  }

  createWorkItemAndChildren(workItem, childTasksToSave: Task[]){
    var resultArray = [];
    this.workItemService.createWorkItem(workItem).subscribe(workItemId => {
      var parentId = workItemId;
      resultArray.push(parentId);
      if (parentId !== null){
        this.createChildWorkItems(parentId, childTasksToSave).subscribe((results: number) => {
          resultArray.push(results);
          this.tfsIdsCreated = resultArray;
        });
      }
    });
  }
like image 418
Jennifer S Avatar asked Mar 05 '26 13:03

Jennifer S


2 Answers

In your situation child is not good candidate for fork join. but here you should use Async /await. fork join send the request in Async manner but Async/await will wait response of each request when you get response attach that response to parent simple, in Async/await request will be in sequeance just like loop. when all request done, return that object here is link of asyn/await https://lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795/

  createWorkItemAndChildTasks(workitem, childTasksToSave: Task[]): any {
    this.workItemService.createWorkItem(workitem).subscribe(workItemId => {
     var parentId = workItemId;
      if (parentId !== null ){
        this.tfsIdsCreated.push(parentId);

    // now create the children on the workItemForm.
    for (let child of childTasksToSave){
//use here Async await when you get response attach to parent 

     this.workItemService.createChildWorkItem(parentId, child).subscribe(task =>{
        if (task !== null){
          console.log(' createWorkItem received child taskid: ' + task);
          this.tfsIdsCreated.push(task);
        }
      });
    }
  }
  return this.tfsIdsCreated;
});

}

like image 177
Shahid Islam Avatar answered Mar 08 '26 19:03

Shahid Islam


If you want to do subtasks in parallel — forkJoin is your choice.

Heres a rough example:

createParent().pipe(
  // switch from parent stream to forkJoin(...children)
  mergeMap(parent =>
    // wait for all children to be created
    forkJoin(children.map(child => createChild(parent, child))).pipe(
      // combine childResults with parent
      map(childResults => {
        // do operations with parent and all children
        parent.childResults = childResults;
        // switch back to parent
        return parent;
      })
    )
  )
)
.subscribe(parent => {
  // ...
})

Note how we subscribe to Observable only once — this is a good practice.

You don't need async await here.

Hope this helps

like image 22
kos Avatar answered Mar 08 '26 21:03

kos