3

In my angular 7 project as part of my component initialisation I am running a sequence of HTTP request. After each request I get the response and then run then next request.

Currently I have put the HTTP request in a service and call them from my component. My HTTP request functions have additional RXJS functions applied including timeout and repeating request via the .pipe function. Error handling is done in the component.

To chain, after one request is complete I then call the next request in another function. I will need the response data of the first request to execute the next responses.

The issue is the current way I have chained just looks really messy and hard to follow.

Is there are a better way to chain HTTP requests?

I know there is a rxjs fork function but a bit confused on how to implement this especially when I have the error handling and pipes.

Note: Errors are handled the same way for requests.

Full code below and thanks in advance.

Component
formData: any;
style: any;
subscribers:any[];

constructor(private webService: WebService){}

ngOnInit(){
 let id: number = 1;
 this.getFormData(id);

}

getFormData(id: number) {
 this.webService.getFormData(id)
 .subscribe(
   data => { 
     this.formData = data;
     this.getFormStyle(this.formData.style_id);

   },
     err => {
      // Error handler
     }
  )
}

getFormStyle(id: number) {
 this.webService.getFormStyle(id)
 .subscribe(
   data => { 
     this.style = data;
     this.getFormSubscribers(this.formData.subscriber_id);

   },
     err => {
      // Error handler
     }
  )
}

getFormSubscribers(id: number) {
 this.webService.getFormSubscribers(id)
 .subscribe(
   data => { 
     this.subscribers = data;
   },
     err => {
      // Error handler
     }
  )
}

WebService

Form Data API

getFormData(id: number): any {
 let headers: any = this.headerService.getHeaders();
 return this.http.get('www.test.com/form/data/' + id, {headers: headers})
    .pipe(timeout(25000))
    .pipe(retryWhen(errors => errors
      .pipe(map((err, index) => {
        // No Error, throw immediately
        if (!err) {
          throw err;
        } 
        // Caught error (ie not disconnected), throw immediately
        if (err.status !== 0) {
          throw err;
        }
        // Disconnection repeat to limit
        if (index === 2) {
          throw err;
        }
        return err;
      }))
      .pipe(delay(2000))))
    .pipe(map(res => res.json()))
}

Form Style API

getFormStyle(style_id:number) {
     let headers: any = this.headerService.getHeaders();
     return this.http.get('www.test.com/form/style/' + style_id, {headers: headers})
        .pipe(timeout(25000))
        .pipe(retryWhen(errors => errors
          .pipe(map((err, index) => {
            // No Error, throw immediately
            if (!err) {
              throw err;
            } 
            // Caught error (ie not disconnected), throw immediately
            if (err.status !== 0) {
              throw err;
            }
            // Disconnection repeat to limit
            if (index === 2) {
              throw err;
            }
            return err;
          }))
          .pipe(delay(2000))))
        .pipe(map(res => res.json()))

}

Form Subscribers API

getFormSubscribers(subscriber_id:number) {
     let headers: any = this.headerService.getHeaders();
     return this.http.get('www.test.com/form/subscribers/' + subscriber_id, {headers: headers})
        .pipe(timeout(25000))
        .pipe(retryWhen(errors => errors
          .pipe(map((err, index) => {
            // No Error, throw immediately
            if (!err) {
              throw err;
            } 
            // Caught error (ie not disconnected), throw immediately
            if (err.status !== 0) {
              throw err;
            }
            // Disconnection repeat to limit
            if (index === 2) {
              throw err;
            }
            return err;
          }))
          .pipe(delay(2000))))
        .pipe(map(res => res.json()))

}
3
  • What are you using to make API calls. Http or HttpClient. It looks like you're using Http which would not make sense as you've also used modern Rxjs syntax which came after Rxjs 5.5 But Http was deprecated before that. So just want to confirm. Is it Http or HttpClient? Commented Jul 10, 2019 at 8:19
  • Use a switchMap to chain observables when you need the previous value. learnrxjs.io/operators/transformation/switchmap.html Commented Jul 10, 2019 at 8:35
  • I am using Angular Http, didn't know it was deprecated though: import { Http } from '@angular/http'; Commented Jul 10, 2019 at 8:51

1 Answer 1

2

you can try async await to sequence the api call.

Component
formData: any;
style: any;
subscribers:any[];

constructor(private webService: WebService){}

ngOnInit(){
 let id: number = 1;
 this.getFormData(id);

}

async getFormData(id: number) {
 this.webService.getFormData(id)
 .subscribe(
   data => { 
     this.formData = data;
     console.log('start');
     await this.getFormStyle(this.formData.style_id);
     await this.getFormSubscribers(this.formData.subscriber_id);
     console.log('end'); // this line will compile once all the await function compilation will completed.
   },
     err => {
      // Error handler
     }
  )
}

getFormStyle(id: number) {
 return new Promise ((resove, reject) => {
    this.webService.getFormStyle(id)
    .subscribe(
     data => { 
       this.style = data;
       resolve(''); // if you want to pass the data you can pass that data in to resolve 
     },
     err => {
      // Error handler
     }
  )
 })
}

getFormSubscribers(id: number) {
 return new Promise ((resolve, reject) => { this.webService.getFormSubscribers(id)
 .subscribe(
   data => { 
     this.subscribers = data;
     resolve(''); // if you want to pass the data you can pass that data in to resolve 
   },
     err => {
      // Error handler
     }
  ))
}

I hope it helps you out.

Sign up to request clarification or add additional context in comments.

5 Comments

thanks for this solution. I need to know when all responses are complete so I can run other init functions. Is there a way to know when the to await functions are completed?
await function are compiled in sequence so if i write console.log('end'); at the and of the await then console.log('end'); will compile after the await function compile.
awesome didn't know this and exactly what I was after! I'll give it go and if all good will put as a solution. Many thanks
@KaTech Welcome 😊😊😊
Perfect works. Thanks again...I wished I knew this sooner could have had alot cleaner code

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.