Vyhledávání na webu

angular - TypeScript funkce vracející undefined


Mám metodu ve třídě níže:

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
  }

}

Můj problém je s příkazem return, vrací undefined. Konzole.log(data) o několik řádků výše vrací hodnotu, kterou chci. Přemýšlím, proč dostávám undefined. Může to být problém s viditelností proměnných (scoping), ale nemohu na to přijít. Co přehlížím?

Odpověď č. 1

Pracujete s asynchronním programováním, nemůžete pozastavit vykonávání kódu a vaše předplatné bude vyřešeno v budoucnu, ale nemůžete předpovědět kdy. console.log() mimo subscribe se vykoná dříve, než je vaše předplatné vyřešeno, proto je to undefined.
A console.log() uvnitř zpětné volání subscribe se zavolá poté, co je předplatné vyřešeno.
Odkazujte na toto pro lepší pochopení.
Co můžete udělat je, že hodnotu můžete uložit do vlastnosti třídy a přistupovat k ní ve vašem šabloně.

  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}}

nebo můžete použít async pipe
AsyncPipe přijímá jako argument observable nebo promise, volá subscribe nebo připojí handler then, a pak čeká na asynchronní výsledek, než jej předá zpět volajícímu.

 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>

ŽIVÁ UKÁZKA

Odpověď č. 2

 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; //

v tomto je asynchronní volání. Protože vracíte hodnotu předtím, než je volání vyřešeno nebo se vrátí, nebudete mít data v this.searchItems, protože používáte volání na server nebo do databáze, použijte observable, abyste využili koncept slibu v Angularu.