I'm developing an app to retrieve data from my API server, compare it to new data, and then push new data (if it doesn't exist) to the API server. Currently I'm working on the functionality to retrieve the existing data on the server using $http, promises and $q.all(). When I push all the promises to an array and then use $q.all(), it fires synchronously and doesn't wait for the promises to resolve.
I've already gone through and, to my knowledge, put in returns in all the operations I want to run asynchronously. I've also read many of the posts with similar problems and made those adjustments with no success.
This is the relevant code from the fileData service:
var apiPromise = function (url) {
var deferred = $q.defer();
$http.get(url)
.then(function (result) {
deferred.resolve(result.data);
return;
});
return deferred.promise;
};
this.GetExistingStudentTest=function(studentid){
return apiPromise('http://localhost:65196/api/PS/GetStudentTests?studentid=' + studentid + '&testid=2')
};
this.GetExistingStudentTestScores = function (testid) {
return apiPromise('http://localhost:65196/api/PS/GetStudentTestScore?testid=' + testid)
};
and the code from the controller that is being used is:
$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;
};
What I need to see is that the test scores return, the test is pushed to the proper array and then the $q.all() resolves to allow the new data and existing data to be compared. What is actually happening is as the inner promises are being resolved, $q.all() resolves and the nested for loop doesn't run because there are no values in the array.