我正在开发一个应用程序,用于从我的API服务器检索数据,将其与新数据进行比较,然后将新数据(如果不存在)推送到API服务器。目前,我正在使用$ http,promise和$ q.all()来检索服务器上现有数据的功能。当我将所有的Promise推送到一个数组,然后使用$ q.all()时,它会同步触发,并且不等待这些Promise解析。
我已经经历了,据我所知,在我要异步运行的所有操作中都添加了返回值。我也阅读了许多存在类似问题的帖子,但所做的调整均未成功。
这是来自fileData服务的相关代码:
$scope.previewUpload = function () {
var promises = [];
for (var i = 0; i < $scope.students.count; i++) {
var student = $scope.students.students[i];
promises.push(fileData.GetExistingStudentTest($scope.students.students[i].studentId)
.then(function (data) {
for (var j = 0; j < data.length; j++) {
var prevTest = {
testId: data[j].id,
studentId: student.studentId,
rawDate: data[j].test_date.substr(5, 2)+data[j].test_date.substr(2,2),
date: data[j].test_date,
testGradeLevel: data[j].grade_level,
scaleScores: {}
};
promises.push(fileData.GetExistingStudentTestScores(prevTest.testId)
.then(function (scoreData) {
console.log(scoreData);
for (var k = 0; k < scoreData.length; k++) {
switch (scoreData[k].testscoreid) {
case "1":
prevTest.scaleScores.english = scoreData[k].numscore;
break;
case "2":
prevTest.scaleScores.math = scoreData[k].numscore;
break;
case "3":
prevTest.scaleScores.reading = scoreData[k].numscore;
break;
case "4":
prevTest.scaleScores.science = scoreData[k].numscore;
break;
case "5":
prevTest.scaleScores.writing = scoreData[k].numscore;
break;
case "6":
prevTest.scaleScores.composite = scoreData[k].numscore;
break;
case "451":
prevTest.scaleScores.ELA = scoreData[k].numscore;
break;
case "452":
prevTest.scaleScores.STEM = scoreData[k].numscore;
break;
}
}
$scope.tests.previous.tests.push(prevTest);
$scope.tests.previous.count++;
return scoreData;
})
);
}
return data;
})
);
}
$q.all(promises).then(function () {
console.log('Completed Test Retrieval');
for (i = 0; i < $scope.tests.refined.count; i++) {
console.log($scope.tests.refined.tests[i]);
console.log($scope.tests.previous)
for (j = 0; j < $scope.tests.previous.count; j++) {
console.log($scope.tests.previous.tests[j]);
if ($scope.tests.previous[j].studentId === $scope.tests.refined[i].studentId && $scope.tests.previous[j].rawDate === $scope.tests.refined[i].rawDate) {
console.log('Match');
}
}
}
});
$scope.validateTests = true;
};
,并且正在使用的来自控制器的代码为:
US( \d+.?\d*)?
我需要看到的是测试分数返回,将测试推送到适当的数组,然后$ q.all()解析以允许比较新数据和现有数据。实际发生的情况是内部承诺被解析,$ q.all()解析且嵌套的for循环不运行,因为数组中没有值。
答案 0 :(得分:2)
首先,我将从摆脱defer
开始,我认为您不需要它。 $http
返回一个承诺,因此您可以做到这一点。请阅读这篇文章,它改变了游戏规则! https://www.codelord.net/2015/09/24/%24q-dot-defer-youre-doing-it-wrong/
var apiPromise = function (url) {
return $http.get(url).then(function (result) {
return result.data;
});
};
第二,您不应在$ q之外的代码上执行可能尚未解析的数据。您需要嵌套该逻辑或编写函数
// get all tests
var tests = students.map(function(s){
return fileData.GetExistingStudentTest(s.studentId)
});
// wait for tests to resolve
$q.all(tests).then(function(resolvedTests){
var transformedTests = // transform logic
// get all test scores
var testScores = transformedTests.map(function(t){
return fileData.GetExistingStudentTestScores(t.testId);
});
// wait for test scores to resolve
$q.all(testScores).then(function(resolvedTestScores){
// you now have all the tests and test scores resolved...
processTests(transformedTests,resolvedTestScores);
});
});