6

Is this the correct way to bind data using Observables? if it is, what else is wrong with my code that makes the selectedCourse variable equal undefined?

    this.golfDataService
      .getGolfData(id)
      .subscribe(data => {
        this.selectedCourse = data.data
        console.log(data.data)
      })
    setTimeout(function () { console.log(this.selectedCourse) }, 2000);
  }

I expect both console.log statements to return the same thing, but only the first console.log returns the data, which is an object with golf course information, but the console.log(this.selectedCourse) returns undefined.

2
  • change it to setTimeout(() => { console.log(this.selectedCourse) }, 2000); if its fast enought it will return correct value. If you use function it rebinds this to that function context not the component Commented Aug 4, 2019 at 23:30
  • you're creating a closure and a race condition, just not good practice all around, use arrow functions and don't rely on timers Commented Aug 4, 2019 at 23:39

2 Answers 2

1

Use arrow function. Then again depending on how fast the getGolfData call is, you 'might' get the value logged. The point it, we shouldn't try to use timers to rely on getting the data, instead develop the code in event driven way.

this.golfDataService
  .getGolfData(id)
  .subscribe(data => {
    this.selectedCourse = data.data;
    console.log(data.data);
  });
setTimeout(() => console.log(this.selectedCourse), 2000);
Sign up to request clarification or add additional context in comments.

1 Comment

I did not even think about that, thank you so much! I know to avoid timers, It was just a quick way to see if the data was even binding, thank you again!
1

I suggest you to not subscribe Observable in component logic unless you explicitly unsubscribe() subscriptions.

A better approach (less code, less complexity, best performance) is to use async pipe provided by Angular.

 this.selectedCourse$ = this.golfDataService
      .getGolfData(id)
      .pipe(
        map(res => res.data),
        tap(x => console.log(x))
      );

Then in template :

<div *ngIf="selectedCourse$ | async as selectedCourse">
  Hello {{selectedCourse}}
</div>

This approach has a lot of benefits like cleaner code, avoid memory leak, easy migration to OnPush change detection strategy and powerful usage of RxJS.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.