动态创建的对象在尝试访问其键值时返回undefined

时间:2018-12-11 12:45:54

标签: javascript angular typescript

我有一个看起来像这样的学生对象...

{
  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,但由于某种原因它只返回一项。 您的帮助将不胜感激。

2 个答案:

答案 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;
    });
}

另外,最好是一次取回所有学生然后过滤它们,而不是只对一个学生发出多个请求(取决于所考虑的学生数量),这是更好的性能选择。

相关问题