cup_of
cup_of

Reputation: 6687

TypeScript function returning undefined

I have a method in a the class below:

export class SearchService {
  userUID: string;
  searchItems: any;
  private searchesCollection: AngularFirestoreCollection;

  constructor(
    private db: AngularFirestore,
    private afAuth: AngularFireAuth,
  ) {
  }

  getSearches() {
    this.afAuth.authState.subscribe(user => {
      this.userUID = user['uid'];
      this.searchesCollection = this.db.collection(`users/${this.userUID}/searches`);
      this.searchItems = this.searchesCollection.valueChanges().subscribe(data => {
        console.log(data); // works
        return data;
      });
    });
    console.log(this.searchItems); // undefined
    return this.searchItems; //undefined
  }

}

My issue is with the return statement, it is returning undefined. The console.log(data) a few lines above it returns the value I want. I am wondering why I am getting undefined. It might be a scoping issue but I can't seem to figure it out. What am I overlooking?

Upvotes: 2

Views: 9397

Answers (2)

Vikas
Vikas

Reputation: 12036

You are working with async programming you cannot pause the execution of the code and your subscription will be resolved in future but you cannot predict when. console.log() outside the subscribe is executed before your subscription is resolved that's why it's undefined
and console.log() inside subscribe call back is invoked after the subscription is resolved.
Refer this for better understanding.
what you can do is You can store the value in a class property and access it in your template.

  getSearches() {
    this.afAuth.authState.subscribe(user => {
      this.userUID = user['uid'];
      this.searchesCollection = this.db.collection(`users/${this.userUID}/searches`);
   this.searchesCollection.valueChanges().subscribe(data => {
        console.log(data); // works
         this.searchItems=data;
      });
    });
    console.log(this.searchItems); // undefined
    return this.searchItems; //undefined
  }

HTML

  {{searchItems?.//property}}

or you can use async pipe
AsyncPipe accepts as an argument an observable or a promise, calls subscribe or attaches a then handler, then waits for the asynchronous result before passing it through to the caller.

 getSearches() {
        this.afAuth.authState.subscribe(user => {
          this.userUID = user['uid'];
          this.searchesCollection = this.db.collection(`users/${this.userUID}/searches`);
       this.searchItems=this.searchesCollection.valueChanges();

      }

HTML

<ng-container *ngFor="let item of searchItems|async">
      {{item?.//property}}
<ng-container>

LIVE DEMO

Upvotes: 2

Sagar Kharab
Sagar Kharab

Reputation: 369

 getSearches() {
    this.afAuth.authState.subscribe(user => {
      this.userUID = user['uid'];
      this.searchesCollection = this.db.collection(`users/${this.userUID}/searches`);
      this.searchItems = this.searchesCollection.valueChanges().subscribe(data => {
        console.log(data); // works
        return data;
      });
    });
    console.log(this.searchItems); // undefined
    return this.searchItems; //

there is an async call in this. Since you are returning the value before your call is resolved or comes back you will not have data in this.searchItems since you are using a call to server or to db, use observable to take advantage of Angular's promise concept.

Upvotes: 1

Related Questions