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.
