Quiero obtener el valor del ID de evento que tengo de mi colección Firestore llamada Eventos. Puedo obtener y mostrar todos mis eventos en mi colección de eventID en mi aplicación, pero necesito este ID de evento para completar otras funcionalidades.
Soy nuevo en TS y Angular y no puedo entender por qué esto no funciona
Cuando registro mi variable de ID de userid dentro de la función de autenticación, funciona bien y recupera el valor, pero si lo hago fuera de la función, da indefinido.
Además, cuando registro toda la variable eventList que creé para almacenar la información de firestore, registra toda la información, pero si trato de recuperar algo, por ejemplo, this.eventList.eventID o this.eventList.title , se registra sin definir.
¿Qué estoy haciendo mal?
aquí está mi código:
import { Component,OnInit } from '@angular/core'; import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/compat/firestore'; import { Observable } from 'rxjs/Observable'; import { AuthService } from '../auth.service'; import { Router } from '@angular/router'; import { async } from '@firebase/util'; export class Tab1Page implements OnInit { public eventList; public userid; constructor(private firestore: AngularFirestore, public fAuth: AuthService, public router: Router) {} ngOnInit(){ this.fAuth.firebaseAuth.user.subscribe(res => { this.userid = res.uid; //current logged in user id //fetch only events logged in user created this.firestore.collection('Events',ref=>ref.where("eventCreator","==",this.userid)).valueChanges().subscribe(event => { this.eventList = event console.log(this.eventList)//logs all the info from firestore console.log(this.eventList.eventID)//logs undefined console.log(this.userid)//logs the userid }); }); console.log(this.userid)//logs undefined } }Para sortear los problemas de respuesta de datos undefined que ocurren con las suscripciones anidadas, use un operador RxJS switchMap() para pasar el resultado del observable externo del observable fAuth.firebaseAuth.user al observable interno, que es this.firestore.collection.. observable, que desde allí puede asignar la lista de eventos de la respuesta transmitida del observable interno, todo dentro de una suscripción:
Así (no estoy seguro de la estructura de los datos de su evento, ya sea una matriz o una clase/interfaz que es un encabezado que contiene una matriz, por lo que he colocado any como tipo de respuesta):
this.fAuth.firebaseAuth.user .pipe( switchMap((res: any) => { this.userid = res.uid; //current logged in user id //fetch only events logged in user created const eventListObservable: Observable<any> = this.firestore.collection('Events',ref => ref.where("eventCreator","==",res.uid)) .valueChanges() .pipe( map((event: any) => { this.eventList = event; console.log(event); //logs all the info from firestore console.log(event.eventid); //logs event id console.log(user.id); //logs the userid return event; }) ); return eventListObservable; }) ) .subscribe(); Como práctica recomendada, puede asignar lo anterior a una subscription y liberarlo más tarde en el controlador ngDestroy() .
Un problema común experimentado es poder acceder a variables fuera del bloque subscribe() y se plantea en esta pregunta . Si intenta acceder a la variable de event del componente fuera (y después) del bloque subscribe() , la variable no estará undefined cuando se acceda a ella porque la ejecución del observable interno asincrónico aún no se ha completado y el código dentro de su controlador aún no se ha completado. ejecutado para inicializar la variable.
Las soluciones al problema del acceso variable fuera del bloque de suscripción incluyen el uso de:
async pipe dentro de la plantilla HTML del componente. (Convierta la variable en un Observable primero).combinelatest() para suscribirse a los observables simultáneamente y manejarlos cuando todos tengan resultados listos de sus respectivos observables.Para experimentar y probar los observables anidados anteriores, primero use servicios simulados simples y luego adjunte sus observables a los servicios en vivo.
Recomiendo un buen sitio de referencia aquí (que también uso con bastante frecuencia) para una comprensión adicional (y ejemplos) y más sobre cómo usar RxJS en estas situaciones y, por supuesto, otras publicaciones en SO.
Como console.log(this.userid) // logs undefined
Como @MikeOne refiere, las funciones dentro de la subscribe son asincrónicas. Estas funciones normalmente se ejecutarán más tarde. Entonces, en el momento en que se ejecuta console.log(this.userid)//logs undefined , this.userid = res.uid; aún no se ejecuta.
Como console.log(this.eventList.eventID) // logs undefined
Supongo que this.eventList es una matriz. Pruebe this.eventList[0].eventID y así sucesivamente para acceder a cada elemento.