Home > Software engineering >  Subscription of observable returns undefined
Subscription of observable returns undefined

Time:03-30

I use a service to fill my observable with data from the backend. The backend is delievering the correct data. Now I want to take the values of the observable and build a piechart.

The part of the Code looks like this:

this.dataSet = this.dataService.getData(this.id);
this.dataSet.subscribe(
x => this.rightData = x.rightCount,
x => this.wrongData = x.wrongCount,
);
console.log('First value: '  this.rightData);
console.log('Second value: '  this.wrongData);
this.pieChartData = [this.rightData, this.wrongData];

It doesn't work and the console output is:

First Value: undefined
Second Value: undefined

But when I change the code to the following, the console log shows the right data:

this.dataSet = this.dataService.getData(this.id);
this.dataSet.subscribe( 
x => console.log(x.rightCount),
x => console.log(x,wrongCount),
);

Output:

3
7

Additional code:

export interface Counter {
  rightCount: number;
  wrongCount: number;
}

dataSet: Observable<Counter> = of();

The service looks like:

getData(id: number): Observable<Counter> {
    return this.http.get<Counter>(`/backend/getData?id=${id}`);
  }

The firefox log shows me, the backend returns:

{"rightCount":3,"wrongCount":7}

Do you have an Idea where I make a mistake?

CodePudding user response:

this behaviour is normal since your code (subscribe) runs asynchronously. It would be the same as:

let test;
setTimeout(() => {this.test = "hello"}, 1000);
console.log(test);

the code above would print undifined right? doing subscribe() is similar to a setTimeoutsince both code runs asynchronously.

also if you would do:

this.dataSet.subscribe(
x => console.log('test1')
);
console.log('test2');

the output would be: test2 test1 because the code inside subscribe asynchronously

the correct code in your case would be:

this.dataService.getData(this.id).subscribe(
  x => {
    this.rightData = x.rightCount;
    console.log('First value: '  this.rightData);
    // this.wrongData is undefined here
    this.pieChartData = [this.rightData, this.wrongData];
  },
  err => {
    this.wrongData = x.wrongCount;
    console.log('Second value: '  this.wrongData);
    // this.rightData is undefined here
    this.pieChartData = [this.rightData, this.wrongData];
  }
);

please note that the Second value / wrongData will only occurr if an error is thrown in this.dataService.getData

CodePudding user response:

You can encapsulate the final manipulation inside the "finaly" in subscribe.

something like this

this.dataSet = this.dataService.getData(this.id);
this.dataSet.subscribe(
  x => (this.rightData = x.rightCount),
  x => (this.wrongData = x.wrongCount),
  () => {
    console.log('First value: '   this.rightData)
    console.log('Second value: '   this.wrongData)
    this.pieChartData = [this.rightData, this.wrongData]
  }
);

Or just

this.dataService.getData(this.id).subscribe(
  x => (this.rightData = x.rightCount),
  x => (this.wrongData = x.wrongCount),
  () => {
    console.log('First value: '   this.rightData)
    console.log('Second value: '   this.wrongData)
    this.pieChartData = [this.rightData, this.wrongData]
  }
);

Note that the "finally" doesn't receive any parameters, it only serves to do manipulations after receiving success or error from the observable

  • Related