一旦订阅填充,Angular就会调用一个函数

时间:2018-05-31 03:35:13

标签: angular angularfire2 angular2-observables

无法为视图逻辑获取正确的值。

基本上调用服务,它运行并填充数组,然后我需要它在数组代码完成时调用私有函数。

calculateSemesterGPA(semesterId: string, userId: string) {

let gradesArr = [];
let resultsArr = [];
let result;

this.getSemesterGrades(semesterId).valueChanges()
.subscribe(snapshots => {
  snapshots.forEach(snapshot => {
    gradesArr.push(snapshot.grade)  
  });
});

this.getScales(userId).valueChanges()
.subscribe(snapshots => {
  snapshots.forEach(snapshot => {
    for(let i = 0; i < gradesArr.length; i++) {
      if(gradesArr[i] === snapshot.letter) {
        resultsArr.push(snapshot.points);
      }
    }
    result = this.CalculateGPA(resultsArr)
  });
})

return result;

}

/*
    Function to calculate the gpa score of an array passed in.
*/
private CalculateGPA(gradePoints: number[]) {

    let length = gradePoints.length;
    let total = 0;

    for(let i = 0; i < length; i++) {
      total += (gradePoints[i]*1);
    }

    // returns the total grade score divided by the amount of grades in the array.
    console.log(total / length)
    return (total / length);
}

我知道私有函数正常工作,因为它是console.log的正确值。但似乎原始函数返回结果而不等待this.getScales部分完成。我也试过直接从那个部分内部返回。

1 个答案:

答案 0 :(得分:1)

您将在subscription之外返回,因此当您的subscription进行并获取数据并进行计算时,您已经返回。退回订阅内部也不是一个好主意。您希望在哪里看到return?什么是valueChanges()subscribe将返回Subscription。为什么不将result作为类变量并在订阅中直接指定它:

this.result = this.CalculateGPA(resultsArr);

现在,如果你真的必须从你的那个方法返回,那么不要subscribe而是做map并且:

return this.getScales(userId).valueChanges().map(() => {
    ...
    return result
    ...
})

然后你必须subscribe返回值。

修改

我刚看到你已经在一个方法下一个接一个地订阅了订阅:calculateSemesterGPA(semesterId: string, userId: string) {}。 我们无法确定哪个订阅会先成功。请将第二个订阅嵌套在第一个订阅项下,这样您就可以确定第二个订阅仅在第一个订阅完成后才运行。

this.getSemesterGrades(semesterId).valueChanges()
   .subscribe(snapshots => {
      snapshots.forEach(snapshot => {
         gradesArr.push(snapshot.grade)  
      });

      this.getScales(userId).valueChanges()
        .subscribe(snapshots => {
          snapshots.forEach(snapshot => {
          for(let i = 0; i < gradesArr.length; i++) {
            if(gradesArr[i] === snapshot.letter) {
              resultsArr.push(snapshot.points);
            }
          }
         this.result = this.CalculateGPA(resultsArr)
         });
        })    
   });