Shailesh Prajapati
Shailesh Prajapati

Reputation: 622

How to async call a method and wait for an API call to complete

I am new to angular and stuck in a scenario where I created two componenrs Student Component and Parent Component:

I have created a seperate file of functions in studentHttpService class for all RESTAPI service for students and I have a method as:

SaveOrUpdateStudent(studentDetail: IStudentDetail): Observable<IStudentDetail> {
    return this.http.post<IStudentDetail>(this.serverurl + '/api/studentdata/SaveOrUpdateStudent', studentDetail);
}



The above service is called in a Student Component where a method SaveStudent() checks for all the required validations and then calls studentHttpService.SaveOrUpdateStudent(studentDetail)

This works fine for student component.

For Parent Component also I have done the similar things:

Created a seperate file of functions in parentHttpService class for all RESTAPI service for parents:

SaveOrUpdateParent(parentDetail: IParentDetail): Observable<IParentDetail> {
    return this.http.post<IParentDetail>(this.serverurl + '/api/parentdata/SaveOrUpdateParent', parentDetail);
}



Now my problem is that in Parent component I have a section to create a new parent and while creating I have a dropdown to select a student from the list of students and on saving the parent detail, the student selected is linked to the parent. With the dropdown feature I also have a button next to dropdown to create a new student and then on clicking the button it opens the student component in a modal (the modal allows user only to enter new student details and it shouldn't save when user clicks on OK button of modal) and I have used the same student component as a child component inside Parent Component. After filling details of student when user clicks on OK button , it populates the name of newly created student in the student dropdown list together with the current value selected

When I save details for parent it should save the newly created student and the parent detail and it should link the newly created student to parent as well.

So for this I tried using async/await where:

I used :

@ViewChild(StudentDetail) studentDetail: StudentDetail;

async SaveParent(): Promise<void> {
    if(newStudentCreated) {
        await studentDetail.SaveStudent();
    }
    await parentHttpService.SaveOrUpdateParent(parentDetail);
}

in my Parent Component class

So if I debug and check it works fine and the new student is linked to Parent. But sometimes it doesn't link when it takes more time to save student data. I tried using :

SaveParent(): Promise<void> {
return new Promise((resolve) => {
    if(newStudentCreated) {
         studentDetail.SaveStudent();
    } 
    resolve();
    }).then(()=> {
     parentHttpService.saveOrUpdateParent(parentDetail)
     });
}



It also has the same problem. Help me out in working in right direction using similar technique.

Upvotes: 1

Views: 527

Answers (2)

Eliseo
Eliseo

Reputation: 58039

Why not use switchMap?

parentHttpService.saveOrUpdateStudent(studentDetail: IStudentDetail).pipe(
   switchMap(res=>{
      ..here you has the response of saveStudent
      ..I supouse you want to change "parentDetail", with the response
      ..e.g. if return a studentId, you can write some like
      parentDetail.studentId=res.studentId
      return parentHttpService.saveOrUpdateParent(parentDetail)
   })).subscribe(res=>{
      ..here the response of saveParent..
   })

Upvotes: 1

DIntriligator
DIntriligator

Reputation: 31

You wouldn't need async or await here. You can do something like this (simplifiying a bit so it may need some work):

saveStudentAndParent(): void {
    studentDetail.saveStudent().pipe(takeUntil(this._destroy$)).subscribe(
        data => this.saveParent(data),
        err => console.log(err)
    )
}

saveParent(data: any): void {
  // Do your check if the student saved successfully then save parent
}

You'll notice I'm using takeUntil to ensure the subscription is unsubscribed, this takes a bit more plumbing then I have here to get working but is fairly simple. All you have to do is set up a Subject called destroy$ and in ngOnDestroy call

this._destroy$.next(true);
this._destroy$.complete();

Calling the saveParent in the subscribe of the save student call ensures that the student call is done before moving on.

Upvotes: 0

Related Questions