angular - 使用firebase将promise值分配给角度全局值时的时间失败
问题描述
当我调用 getProyectos () 时出现问题,因为它在变量 this.students 还没有值时拉取变量并且我收到此错误:
ERROR Error: Uncaught (in promise): TypeError: alumnos is not iterable
TypeError: alumnos is not iterable
at AdminpanelComponent.getProyectos (adminpanel.component.ts:300)
at AdminpanelComponent.<anonymous> (adminpanel.component.ts:244)
at Generator.next (<anonymous>)
at tslib.es6.js:73
at new ZoneAwarePromise (zone-evergreen.js:876)
at Module.__awaiter (tslib.es6.js:69)
at AdminpanelComponent.ngOnInit (adminpanel.component.ts:220)
at checkAndUpdateDirectiveInline (core.js:31910)
at checkAndUpdateNodeInline (core.js:44367)
at checkAndUpdateNode (core.js:44306)
at resolvePromise (zone-evergreen.js:797)
at new ZoneAwarePromise (zone-evergreen.js:879)
at Module.__awaiter (tslib.es6.js:69)
at AdminpanelComponent.ngOnInit (adminpanel.component.ts:220)
at checkAndUpdateDirectiveInline (core.js:31910)
at checkAndUpdateNodeInline (core.js:44367)
at checkAndUpdateNode (core.js:44306)
at debugCheckAndUpdateNode (core.js:45328)
at debugCheckDirectivesFn (core.js:45271)
at Object.eval [as updateDirectives] (AdminpanelComponent_Host.ngfactory.js? [sm]:1)
这是ngOninit()的代码
ngOnInit () {
this.getAlumnos ();
this.alumnosProyectos = this.getProyectos ();}
这是 getAlumnos() 和 getProyectos() 的代码
async getAlumnos() {
await this.firestoreService.getUsuarios().subscribe((UsuariosSnapshot) => {
this.alumnos = [];
UsuariosSnapshot.forEach((alumnoData: any) => {
if (alumnoData.payload.doc.data().rol == "Alumno") {
this.alumno = {
usuario: {
id: null,
data: null
}
};
this.alumno.usuario.id = alumnoData.payload.doc.id;
this.alumno.usuario.data = alumnoData.payload.doc.data();
this.alumnos.push(this.alumno);
}
})
});
}
getProyectos() {
let proyectos = []
for (let alumno of this.alumnos) {
let query2 =this.firestoreService.getProyectosUsuario(alumno.usuario.id).subscribe((usuario) => {
if (usuario.length > 0) {
proyectos.push({
id: alumno.usuario.id,
data: usuario[0].payload.doc.data()
});
}
});
}
console.log("aqui", proyectos);
return proyectos;
}
还附上了firebase服务代码
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class FirestoreService {
constructor(private firestore: AngularFirestore) { }
public getUsuarios() {
return this.firestore.collection('alumnos').snapshotChanges();
}
public getProyectosUsuario(documentId: string){
return this.firestore.collection('alumnos').doc(documentId).collection('proyectos').snapshotChanges();
}
非常感谢您的回复,在此先感谢。
解决方案
您可以在另一个函数中扭曲您的两个函数并使用 await 关键字,以等待您的 getAlumnos() 函数完成,然后再继续。嗨已经重写了你的代码,所以我应该工作。
ngOnInit () {
this.SomeFunctionName()
}
async getAlumnos() {
this.alumnos = [];
await this.firestoreService.getUsuarios().subscribe((UsuariosSnapshot) => {
UsuariosSnapshot.forEach((alumnoData: any) => {
console.log('alumno',alumnoData.payload.doc.data())
if (alumnoData.payload.doc.data().rol == "Alumno") {
const alumno = {
usuario: {
id: null,
data: null
}
};
alumno.usuario.id = alumnoData.payload.doc.id;
alumno.usuario.data = alumnoData.payload.doc.data();
this.alumnos.push(this.alumno);
}
})
return this.alumnos;
});
}
getProyectos() {
let proyectos = []
for (let alumno of this.alumnos) {
let query2 =this.firestoreService.getProyectosUsuario(alumno.usuario.id).subscribe((usuario) => {
if (usuario.length > 0) {
proyectos.push({
id: alumno.usuario.id,
data: usuario[0].payload.doc.data()
});
}
});
}
console.log("aqui", proyectos);
this.alumnosProyecto = proyectos;
}
async SomeFunctionName(){
await getAlumnos();
getProyectos();
}
解决此问题的另一种方法是将所有内容包装在管道中,因此函数按顺序执行,但是由于您使用异步等待,因此正如我刚刚演示的那样更容易做到。
更新的解决方案
这是有关如何使用 SwitchMap 解决它的示例
SomeFunctionName() {
this.alumnos = [];
this.firestoreService.getUsuarios().pipe(switchMap((UsuariosSnapshot: any) => {
UsuariosSnapshot.forEach((alumnoData: any) => {
//console.log('alumno', alumnoData.payload.doc.data())
//if (alumnoData.payload.doc.data().rol == "Alumno") {
const alumno = {
usuario: {
id: null,
data: null
}
};
alumno.usuario.id = alumnoData.payload.doc.id;
alumno.usuario.data = alumnoData.payload.doc.data();
this.alumnos.push(alumno);
//}
})
return of(this.alumnos);
})).subscribe(alumnos => {
let proyectos = []
this.alumnos.forEach(alumno => {
let query2 = this.firestoreService.getProyectosUsuario(alumno.usuario.id).subscribe((usuario) => {
if (usuario.length > 0) {
proyectos.push({
id: alumno.usuario.id,
data: usuario[0].payload.doc.data()
});
}
});
})
console.log("aqui", proyectos);
this.alumnosProyectos = proyectos;
})
}
请记住将这两行添加到您的导入中
import { switchMap } from 'rxjs/operators/';
import { of } from 'rxjs';
希望有帮助。
推荐阅读
- python - 在 HBox 容器中将两个 ipywidgets textAreas 扩展到最大
- angular - 自定义元素(聚合物)属性绑定到 Angular 9 中的 RxJS Observable
- c - 是否可以仅在缓冲区末尾存储 n-1 个字符?
- c# - 我可以强制 Json.NET 从根目录开始树反序列化吗
- excel - VBA 编码变量属性的类型不正确
- css - 如何将 css 文件添加到 R Shiny 以改进我的应用程序?
- python - 当输入是字母而不是数字时,Python 说 (ValueError: invalid literal for int() with base 10: '')
- paypal - 我怎样才能避免为同一个买家订阅同一个planid?
- c# - 有什么方法可以防止/检测自动/隐式类型转换?
- c# - 创建一种可以访问许多不同上下文数据库表的通用方法