Alexis
Alexis

Reputation: 59

JS wait for a funtion until it receives data

I'm always stuck when it come to acronyms methods, because of that I'm expriencing some issues with my code. Hope you guys can help me.

So basically, I have 2 funtions on the onInit; however, when "fetchSalesbyDay2" runs, the this.firstResponse is reciving undefined and not saving the first reponse from "fetchSalesbyDay1 "

ngOnInit(): void {
    this.fetchSalesbyDay1();
    this.fetchSalesbyDay2();
}

fetchSalesbyDay1 = async () => {
    const params = {
        'reportName': 'home_report',
        'query': {
            'metric': 'salesByDay',
            'showBy': this.period.toString(),
            'startDate': parseInt(moment(this.range1sDate, 'MM-DD-YYYY HH:mm').format('X'), 10),
            'endDate': parseInt(moment(this.range1eDate, 'MM-DD-YYYY HH:mm').format('X'), 10)
        }
    };

    await this.http
        .post(this.GLOBALURL + '/reports/query', params, this.httpOptions1)
        .subscribe((response: any) => {
            this.firstResponse = response;
        });
}

fetchSalesbyDay2 = async () => {
    const params = {
        'reportName': 'home_report',
        'query': {
            'metric': 'salesByDay',
            'showBy': this.period.toString(),
            'startDate': parseInt(moment(this.range2sDate, 'MM-DD-YYYY HH:mm').format('X'), 10),
            'endDate': parseInt(moment(this.range2eDate, 'MM-DD-YYYY HH:mm').format('X'), 10)
        }
    };
    await this.http
        .post(this.GLOBALURL + '/reports/query', params, this.httpOptions1)
        .subscribe((response: any) => {
            this.secondResponse = response;
            this.displayandprocessWeekData(this.firstResponse, this.secondResponse);
        });
}

I would like that, once "fetchSalesbyDay1" finishes, and this.firstResponse has already a value, the "fetchSalesbyDay2" can execute. What would be the best way to solve this ?

Upvotes: 0

Views: 91

Answers (3)

Barremian
Barremian

Reputation: 31125

There's essentially no reason to convert the observables to promises. Observables provide better options to combine async data. In this specific case you could use RxJS forkJoin function to combine both the observables

Try the following

import { forkJoin, Observable } from 'rxjs';

ngOnInit(): void {
  forkJoin({          // <-- use `forkJoin` to trigger HTTP requests in parallel
    firstRes: this.fetchSalesbyDay1(),
    secondRes: this.fetchSalesbyDay2()
  }).subscribe({
    next: ({firstRes, secondRes}) => {
      this.displayandprocessWeekData(firstRes, secondRes);
    },
    error: error => {
      console.log(error);
      // handle error
    }
  });
}

fetchSalesbyDay1(): Observable<any> { // <-- return the observable
  const params = {
    'reportName': 'home_report',
    'query': {
      'metric': 'salesByDay',
      'showBy': this.period.toString(),
      'startDate': parseInt(moment(this.range1sDate, 'MM-DD-YYYY HH:mm').format('X'), 10),
      'endDate': parseInt(moment(this.range1eDate, 'MM-DD-YYYY HH:mm').format('X'), 10)
    }
  };

  return this.http.post(this.GLOBALURL + '/reports/query', params, this.httpOptions1);
}

fetchSalesbyDay2(): Observable<any> { // <-- return the observable
  const params = {
    'reportName': 'home_report',
    'query': {
      'metric': 'salesByDay',
      'showBy': this.period.toString(),
      'startDate': parseInt(moment(this.range2sDate, 'MM-DD-YYYY HH:mm').format('X'), 10),
      'endDate': parseInt(moment(this.range2eDate, 'MM-DD-YYYY HH:mm').format('X'), 10)
    }
  };
  
  return this.http.post(this.GLOBALURL + '/reports/query', params, this.httpOptions1);
}

Upvotes: 1

Michael S. Molina
Michael S. Molina

Reputation: 732

Without changing your code you can add await outside your fetch functions like this:

fetchSales = async () => {
   await fetchSalesbyDay1();
   await fetchSalesbyDay2();
}

This way fetchSalesbyDay2() will wait for the first one to complete.

Upvotes: 1

Michał Tkaczyk
Michał Tkaczyk

Reputation: 736

You don't need to use async/await with observables. If you want to execute another function after response comes, just execute it inside your subscribe after property assignment, just like that:

.subscribe((response: any) => {
    this.firstResponse = response;
    this.fetchSalesByDay2();
});

And you can remove all async/await.

Upvotes: 0

Related Questions