Angular 订阅填充后调用函数
Angular calling a function once the subscription has populated
无法为视图逻辑获取正确的值。
基本上服务被调用,它运行并填充一个数组,然后我需要它在数组代码完成时调用一个私有函数。
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 部分完成的情况下返回结果。我也尝试过直接从该部分内部返回。
您 return 在您的 subscription
之外,因此当您的 subscription
正在获取数据并进行计算时,您已经 return 了。返回订阅内部也不是一个好主意。您希望在哪里看到 return
?什么是 valueChanges()
。一个subscribe
将return一个Subscription
。你为什么不把 result
作为一个 class 变量并在你的订阅中像这样直接分配它:
this.result = this.CalculateGPA(resultsArr);
现在,如果您真的必须 return 从您的那个方法,那么不要 subscribe
而是做一个 map
和:
return this.getScales(userId).valueChanges().map(() => {
...
return result
...
})
然后您必须 subscribe
到 returned 值。
编辑
我刚刚看到您将订阅一个接一个地放在一种方法下: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)
});
})
});
无法为视图逻辑获取正确的值。
基本上服务被调用,它运行并填充一个数组,然后我需要它在数组代码完成时调用一个私有函数。
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 部分完成的情况下返回结果。我也尝试过直接从该部分内部返回。
您 return 在您的 subscription
之外,因此当您的 subscription
正在获取数据并进行计算时,您已经 return 了。返回订阅内部也不是一个好主意。您希望在哪里看到 return
?什么是 valueChanges()
。一个subscribe
将return一个Subscription
。你为什么不把 result
作为一个 class 变量并在你的订阅中像这样直接分配它:
this.result = this.CalculateGPA(resultsArr);
现在,如果您真的必须 return 从您的那个方法,那么不要 subscribe
而是做一个 map
和:
return this.getScales(userId).valueChanges().map(() => {
...
return result
...
})
然后您必须 subscribe
到 returned 值。
编辑
我刚刚看到您将订阅一个接一个地放在一种方法下: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)
});
})
});