我有一个看起来像这样的学生对象...
{
Freshmen: [{id: 3}, {id: 5}],
Sophomores: [{id: 2}, {id: 6}],
Juniors: [{id: 1}, {id: 8}],
Seniors: [{id: 9}, {id: 4}, {id: 7}]
}
我需要根据数组中的ID查找学生。我需要返回的是一个看起来完全相同的对象,但是现在从数据库中检索了完整的对象,而不是仅包含id的对象。
在我的angular component.ts文件中,我尝试通过以下方式进行操作...
private getStudents(obj) {
const result = {};
for (const key of Object.keys(obj)) {
obj[key].map(item => {
this.studentsService.geStudentById(item.id).subscribe(res => {
result[key] = [];
result[key].push(res);
});
});
}
return result;
}
我有一个注入到组件中的服务。该服务具有一种通过ID获取学生的方法,我在getStudents()
中调用该服务方法。该服务返回各自的学生对象,然后将它们推入数组。
稍后,我像这样调用函数并将结果分配给变量studentDetails
...
this.studentDetails = this.getStudents(studentObj);
一切似乎都正常,除了当我尝试做...... console.log(this.StudentDetails.Freshmen);
时,我得到undefined
。
我是按照正确的方式进行操作吗?还是有一些更好的方法可以处理它,例如使用arr.reduce()
而不是arr.map()
?尽管我尝试过reduce,但由于某种原因它只返回一项。
您的帮助将不胜感激。
答案 0 :(得分:1)
您正在异步调用,然后返回result
。发生的情况是您的函数在所有请求完成之前将返回一个空对象{}
。
您需要这样的东西(需要一些重构):
function getStudents(obj) {
const result = {};
const requests= [];
for (const key of Object.keys(obj)) {
obj[key].forEach(item => {
let currentRequest = this.studentsService.geStudentById(item.id)
.subscribe(res => {
result[key] = [];
result[key].push(res);
});
requests.push(currentRequest)
});
}
return Observable.forkJoin(...requests).subscribe(() => {
return result;
})
}
然后像这样设置studentDetails
道具:
this.getStudents(studentObj).subscribe(result => this.studentDetails = result)
答案 1 :(得分:1)
问题是您的return
语句在异步getStudentById()
请求完成之前就已执行。
我建议使用RxJS,然后将请求压缩在一起,并在获得所有请求结果后对数据进行处理。
使用RxJS,您的函数可能如下所示:
private getStudents(obj) {
const result = {};
// Array to store all the observables
let observables: Observables<void>[] = [];
// Generate all the observables with the respective parameters
for (const key of Object.keys(obj)) {
obj[key].map(item => {
observables.push(
this.studentsService.geStudentById(item.id)
.map(res => {
result[key] = [];
result[key].push(res);
});
});
);
}
// Zip them together and wait for all of them to emit a value
of(...observables)
.pipe(zipAll())
.subscribe(() => {
return result;
});
}
另外,最好是一次取回所有学生然后过滤它们,而不是只对一个学生发出多个请求(取决于所考虑的学生数量),这是更好的性能选择。