Reputation: 53
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
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
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