[英]Loading images together with short list of users in Angular ngOnInit method fails, images are always undefined
我有一个页面包含一些引导卡(大约 2 到 5 张)。 他们提供学生信息。 我还想(从服务器)加载这些学生的图像及其详细信息,但我不知道如何。 这是我得到的:
students: { student: Student, hasImage: boolean, image: any }[] = [];
loadingData: boolean;
imageToShow: any;
constructor(private userService: UsersService, private fileService: FilesService) {
}
createImageFromBlob(image: Blob) {
const reader = new FileReader();
reader.addEventListener('load', () => {
this.imageToShow = reader.result;
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
ngOnInit() {
this.userService.getStudentsOfLoggedUser().subscribe(res => {
this.loadingData = true;
res.forEach(std => {
if (std.imageUrl == null) {
this.students.push({student: std, hasImage: false, image: undefined});
} else {
this.fileService.getImage(std.imageUrl).subscribe(data => {
this.createImageFromBlob(data);
});
this.students.push({student: std, hasImage: true, image: this.imageToShow});
}
this.loadingData = false;
});
});
}
此代码无法从服务器获取图像,它们总是丢失(未定义)。 它应该是什么样子才能使它正确?
你必须把this.students.push({student: std, hasImage: true, image: this.imageToShow}); 在this.fileService.getImage订阅中,因为它的执行是异步的。
另一方面,您必须避免订阅嵌套。 检查此链接https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs
此外,如果您使用订阅,则必须在 ngOnDestroy 方法中取消订阅,以避免 memory 泄漏。 检查此其他链接https://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/
我希望它对你有用
问候
据我了解,发生这种情况的原因是因为 forEach 本质上是同步的,但这条特定的行是异步的:
this.fileService.getImage(std.imageUrl).subscribe(data => {
this.createImageFromBlob(data);
});
相反,您可以像这样承诺:
this.userService.getStudentsOfLoggedUser().subscribe(res => {
this.loadingData = true;
let count = 0;
new Promise((resolve, reject) => {
res.forEach(std => {
count++;
if (std.imageUrl == null) {
this.students.push({ student: std, hasImage: false, image: undefined });
} else {
this.fileService.getImage(std.imageUrl).subscribe(data => {
this.createImageFromBlob(data);
});
this.students.push({ student: std, hasImage: true, image: this.imageToShow });
}
if (count > res.length -1) {
resolve(); //Resolve condition
}
});
}).then(() => {
this.loadingData = false;
})
});
这样,只有在完成所有异步调用后,您的代码才会被解析,从而防止您获取未定义的数据。
将所有建议和答案组合在一起后,工作代码如下所示:
createImageFromBlob(studentCard: StudentCard, image: Blob) {
const reader = new FileReader();
reader.addEventListener('load', () => {
studentCard.image = reader.result
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
ngOnInit() {
this.userService.getStudentsOfLoggedUser().subscribe(res => {
this.loadingData = true;
res.forEach(std => {
const studentCard = new StudentCard();
studentCard.student = std;
if (!std.imageUrl || std.imageUrl == null) {
studentCard.hasImage = false;
} else {
studentCard.hasImage = true;
}
this.students.push(studentCard);
});
let count = 0;
this.students.forEach(std => {
if (std.hasImage) {
count++;
new Promise((resolve, reject) => {
this.fileService.getImage(std.student.imageUrl).subscribe(data => {
this.createImageFromBlob(std, data);
console.log(std);
});
if (count > this.students.length - 1) {
resolve(); //Resolve condition
}
}).then(() => {
// there is nothing to do here
});
}
});
this.loadingData = false;
});
}
除了匿名类型,我声明 StudentCard 用于交换数据:
export class StudentCard {
student: Student;
hasImage: boolean;
image: any;
}
现在所有图像都按预期出现在屏幕上
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.