Gustavo Kotarsky
Gustavo Kotarsky

Reputation: 53

Getting values outside the subscribe

I'm trying to use some values to shown in graphs, but when I got out the subscribe function the value returned is undefined

I already tried to put in an array of objects and still think this is the right way to do it, but again, when the function go out the subscribe, the values disapear.

ngOnInit() {
    this.getActiveVulForYear(2019);
    console.log(this.vulYearCount); // Here, all the values are printed correctly
    console.log(this.vulYearCount[1]);// Here, the value printed is undefined
}

getActiveVulForYear(year) {
    for (var i = 0; i <= 11; i++) {
      this.activeVulnerabilitiesByMonth(i, year)
    }
}

activeVulnerabilitiesByMonth(month, year) {
    return this.scanvulService.getScanvuls().pipe(
      map((reports: Scanvul[]) =>
        reports.filter(r => {
          this.arrayVulMonth = new Array()
          this.arrayVulMonth = r.data.split('-')
          return this.arrayVulMonth[1] == month && this.arrayVulMonth[0] == year
        }))).subscribe(
          vulsForYear => {
            this.vulsForYear = vulsForYear
            this.vulYearCount[month] = this.vulsForYear.length;            
          }
    );
}

At some point I did an array of objects with two parameters: month and count. When I tried to print the count, for some reason the parameters are 0. But when I print the full array, the prints shown all the parameters correctly (with the right count and month)

Does someone know how to fix this? Thanks!

Upvotes: 1

Views: 1809

Answers (2)

frido
frido

Reputation: 14139

Observables are executed asynchronously so if you want to do something when they emit a value or complete (e.g. log emitted values) you have to do it in the subscribe function. A function that returns an Observable returns immediately and not when the Observable emits a value. You should also subscribe late instead of early. Work with Observables as long as you can and only subscribe when you actually need values from the Observable, i.e. in ngOnInit where you want to log the results.

So activeVulnerabilitiesByMonth and getActiveVulForYear should return Observables. Subscribe to getActiveVulForYear in ngOnInit and log or set global variables that you want to bind to in the template in the subscribe function.

getActiveVulForYear also currently leads to this.scanvulService.getScanvuls() being called 12 times. If one call to this.scanvulService.getScanvuls() returns all data and you only want to filter or rearange the returned data, just fetch the data once and then filter or map it accordingly.

I think this is what your code should look like:

ngOnInit() {
  getActiveVulForYear(2019).subscribe(vulsForYear => {
    this.vulsForYear = vulsForYear;
    this.vulYearCount = vulsForYear.map(vulsForMonth => vulsForMonth.length);
    console.log(this.vulYearCount);
    console.log(this.vulYearCount[1]);
  })
}

getActiveVulForYear(year: number): Observable<Scanvul[][]> {
  return this.scanvulService.getScanvuls().pipe(
    map((reports: Scanvul[]) => {
      let vulsForYear: Scanvul[][] = Array.from({length: 12}, (v, i) => []);
      reports.forEach(r => {
        let yearMonth = r.data.split('-');
        if (yearMonth[0] == year) {
          vulsForYear[yearMonth[1]].push(r);
        }
      })
      return vulsForYear;
    })
  );
}

getActiveVulnerabilitiesByMonth(month: number, year: number): Observable<Scanvul[]> {
  return this.getActiveVulForYear(year).pipe(map(vulsForYear => vulsForYear[month]));
}

https://stackblitz.com/edit/rxjs-bvksfn

Upvotes: 1

Andrey
Andrey

Reputation: 2078

not sure why you say that

console.log(this.vulYearCount); // Here, all the values are printed correctly

actually vulYearCount should be empty at that point.

the array vulYearCount gets fullfilled later, when your scanvulService.getScanvuls() pulls the data and passes it to the pipe where you fullfill array.

Upvotes: 0

Related Questions