简体   繁体   中英

Subscription of observable returns undefined

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?

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 setTimeout since 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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM