Soy nuevo en observables en angular. Tengo un problema en el que quiero devolver un valor dentro de un método de suscripción. Tengo el siguiente método ( getFirebaseData(idForm:string):observable <any[]> ):
getTotalQuestions(idForm:string){ let totalQuestions:number; this.getFirebaseData(idForm+"/Metadatos") .subscribe(items => { items.map(item => { totalQuestions=item.Total; console.log(totalQuestions); }); } ); console.log(totalQuestions); return totalQuestions; } el primer console.log(totalQuestions) imprime 4 pero el segundo console.log(totalQuestions) imprime undefined . Entiendo que subscribe es una operación asíncrona y por eso el segundo console.log(totalQuestions) ("Para escribir el código") imprime indefinido, pero no encuentro la forma de devolver la variable después de que se ha realizado el método subscribe terminado. Ahora, si cambio la suscripción al mapa:
getTotalQuestions(idForm:string){ let totalQuestions:number; this.getFirebaseData(idForm+"/Metadatos") .subscribe(items => { items.map(item => { totalQuestions=item.Total; console.log(totalQuestions); }); } ); console.log(totalQuestions); return totalQuestions; } el primer console.log(totalQuestions) no imprime nada y el segundo console.log(totalQuestions) imprime sin definir. Es algo que no entiendo por qué sucede.
Espero me puedan ayudar a aclarar el concepto que no entiendo. ¡Gracias!
No puede devolver directamente preguntas totales como esa, necesita usar un tema para lograrlo.
getTotalQuestions(idForm:string): Observable<string> { let totalQuestions:number; var subject = new Subject<string>(); this.getFirebaseData(idForm+"/Metadatos") .subscribe(items => { items.map(item => { totalQuestions=item.Total; console.log(totalQuestions); subject.next(totalQuestions); }); } ); return subject.asObservable(); } Uso: getTotalQuestion(idForm).subscribe((r)=>console.log(r))
Para resolver esto crearía una propiedad totalQuestions$ un observable
En el archivo TS
totalQuestions$ = this.getFirebaseData(idForm + "/Metadatos").pipe( map(items => items.reduce((prev, {Total}) => prev + Total), 0))) ) Y ahora en su plantilla puede usar tubería async
<span>{{ totalQuestions$ | async }}</span> Si desea usar la variable en su archivo TS, puede usar operadores combinados como forkJoin o combineLatest para acceder a este valor
newVariable$ = combineLatest([totalQuestions$, ...]).pipe( map(([totalQuestions, ... ]) => { // Perform an operation here and return a value }) )Observable se ejecuta cuando se suscribe a él y lo que regresa de la suscripción siempre es un objeto de suscripción como setInterval. primer ejemplo: debido a que se trata de una llamada asíncrona, el segundo console.log no esperará a que finalice la suscripción antes de ejecutarse.
getTotalQuestions(idForm: string) { let totalQuestions: number; return this.getFirebaseData(idForm + "/Metadatos").pipe( map(items => items.map(item => { totalQuestions = item.Total; console.log(totalQuestions); }); )); } getTotalQuestions('231').subscribe(console.log)