user11952136
user11952136

Reputation:

How to manage asynchronous properly

my code outputs everytime different numbers. Is this a proper way I am using it? Here is the code:

export class GetPlanetsService {
  url='https://swapi.co/api/planets/?page=';
  planets:Planet[]=[];
  headers: HttpHeaders = new HttpHeaders()
    .set('Accept', 'application/json');

  constructor(private http:HttpClient) { }


  getPlanet(pageIndex){                                          
    return this.http.get<Planets>(`${this.url}${pageIndex}`,{headers:this.headers});
  }
  getAllPlanets(){
    let numberOfPages=7;  // Tried to do it dynamically but got infinite loop
    for(let j=1;j<=numberOfPages;j++){
      this.getPlanet(j).subscribe(value=>{
        for(let i=0;i<value.results.length;i++){
          this.planets.push(value.results[i]);
          if(j==numberOfPages && i==(value.results.length-1)){
            console.log(this.planets);  //There is outputted everytime different number
          }
        }     

    });

    }
  } 

Have you got any tips and could you explain it in simple words? Regards

Upvotes: 2

Views: 73

Answers (3)

Maxime G&#233;linas
Maxime G&#233;linas

Reputation: 2330

Ok there is deeper problemes here.

First, why are you trying to call the server 7 times in a row? What if I want page 200? You will make 200 Http requests? The server should return the entire list. It will increase performance and reduce complexity on client side.

Also, why getAllPlanets() return void? It's not intuitive. Instead, getAllPlanets() should return Observable<Planet[]>. All functions should either return of modify (it's part of the CQS principle) here the purpose it to return data so you can't notify your object state e.g. this.planets.push(value.results[i]). What if a invoke the function twice? Then, this.planets will contain the result of both requests.

Upvotes: 0

Saurabh Yadav
Saurabh Yadav

Reputation: 3386

You can use forkJoin for this, Dont forget to include

import { forkJoin } from 'rxjs';

forkJoin waits for each HTTP request to complete and group’s all the observables returned by each HTTP call into a single observable array and finally return that observable array.

getPlanet(pageIndex) {
        return this.http.get < Planets > (`${this.url}${pageIndex}`, {
            headers: this.headers
        });
    }

    getAllPlanets() {
        const response = [...Array(7).keys()].map(i => this.getPlanet(i));
        return forkJoin(response);
    }

in your component you can call getAllPlanets

this.getPlanetsService.getAllPlanets()
    .subscribe(res => {
      console.log(res);
    }, err => {
      console.log(err);

 });

Upvotes: 2

Madhav Palshikar
Madhav Palshikar

Reputation: 312

There are few ways you can control your async behavior.

  1. Promises.all
  2. Async Await
  3. Async library

Upvotes: 0

Related Questions