Nooh Ahamad
Nooh Ahamad

Reputation: 393

How to I make sure a certain function gets executed after another in Angular?

I am currently trying to implement a membership portal in which when I submit a form, I want to post the member and immediately retrieve the value of the member from the ID number that is entered.

My submit function is as follows:

submitForm() {
    const data = this.memberForm.value;
    console.log(data);
    this.service.postNewMember(data.title, data.firstname, data.surname, data.telRes, data.faxNbr, data.email, data.idNbr);
      
    this.service.getMember(data.idNbr).subscribe((res: any) => {
        console.log(res);
    }, (err: any) => {
        console.log(err);
    });
}

The two functions in my service are given below:

getMember(idNbr: string) {
    return this.http.get(this.url + '/crm/getMember/'+ idNbr)
}

postNewMember(title: string, firstName: string, surName: string, telRes: string, faxNbr: string, email: string, idNbr: string) {
    const headers = new HttpHeaders().set('Content-Type', 'application/json');

    const newMember = {
      title: title,
      firstName: firstName,
      surName: surName,
      telRes: telRes,
      faxNbr: faxNbr,
      email: email,
      idNbr: idNbr
    }

    this.http.post(this.url + '/crm/postNewMember', JSON.stringify(newMember), { headers: headers }).subscribe((res: any) => {
      console.log(res);
    })
    
}

I have tested both the service calls separately and they each work well, but what tends to happen is that the get method get's called before the post method has finished execution, and hence I get an error logged in my console, while having the data inserted as needed. However I need the get method data to perform further operations on it, hence I need it to be executed after the post method.

How do I ensure the service.getMember() gets executed after the service.postNewMember()?

Upvotes: 0

Views: 149

Answers (2)

NVK
NVK

Reputation: 26

HTTPClient methods returns Observables and uses the RxJS implementation. To handle the results of these, you can chain your calls together using the pipe operator from RxJS to pass the return values from one function to another without having to subscribe. From the Angular documentation

You can use pipes to link operators together. Pipes let you combine multiple functions into a single function. The pipe() function takes as its arguments the functions you want to combine, and returns a new function that, when executed, runs the composed functions in sequence.

In what OP describes, details on error handling aren't described, so this answer will keep it simple and use finalize as a way to guarantee sequential order. In practice, you may want to use some other operators such as catchError. I'd recommend the operator decision tree as a quick guide.

First let's change your postNewMember call so that it returns the observable directly. Subscribe doesn't return one.

postNewMember(title: string, firstName: string, surName: string, telRes: string, faxNbr: string, email: string, idNbr: string) {
  const headers = new HttpHeaders().set('Content-Type', 'application/json');

  const newMember = {
    title: title,
    firstName: firstName,
    surName: surName,
    telRes: telRes,
    faxNbr: faxNbr,
    email: email,
    idNbr: idNbr
  }

  return this.http.post(this.url + '/crm/postNewMember', JSON.stringify(newMember), { headers: headers });

}

Now let's also imagine a postThenGet function inside your service. I'm not going to re-list all the parameters for your function.

postThenGet(...args /*all the data fields you'd like*/, idNbr: string) {
  return this.service.postNewMembers(.../*all the arguments postNewMembers takes*/).pipe(
    finalize(this.service.getMember(idNbr)
  );
}

Important note, these are not the Pipes that Angular provides. This is specifically an RxJS construct. Angular follows the RxJS library so you may as well use this and its documentation provides a lot of detail for smaller examples.

Then inside your component or service with the submitForm() method

submitForm() {
  const data = this.memberForm.value;
  console.log(data);
  this.service.postThenGet(data.title, data.firstname, data.surname, data.telRes, data.faxNbr, data.email, data.idNbr).subscribe(
  /* From how finalize was used, this will return the result of the get operator */
  (res: any) => {
      console.log(res);
  }, (err: any) => {
      console.log(err);
  });
}

Upvotes: 1

Panagiotis Bougioukos
Panagiotis Bougioukos

Reputation: 18939

First let your postNewMember to return an observable

getMember(idNbr: string) {
    return this.http.get(this.url + '/crm/getMember/'+ idNbr)
}

postNewMember(title: string, firstName: string, surName: string, telRes: string, faxNbr: string, email: string, idNbr: string) {
    const headers = new HttpHeaders().set('Content-Type', 'application/json');

    const newMember = {
      title: title,
      firstName: firstName,
      surName: surName,
      telRes: telRes,
      faxNbr: faxNbr,
      email: email,
      idNbr: idNbr
    }

    return this.http.post(this.url + '/crm/postNewMember', JSON.stringify(newMember), { headers: headers });        
}

Then when you call it use subscribe to call also getMember

    submitForm() {
        const data = this.memberForm.value;
        console.log(data);
        this.service.postNewMember(data.title, data.firstname, data.surname, data.telRes, data.faxNbr, data.email, data.idNbr).subscribe( (res) => {

      this.service.getMember(data.idNbr).subscribe((res2: any) => {
            console.log(res2);
        }, (err: any) => {
            console.log(err);
        });
 });
    }

Upvotes: 1

Related Questions