$ q.all () работает синхронно, а не асинхронно - PullRequest
0 голосов
/ 03 января 2019

Я разрабатываю приложение для извлечения данных с моего API-сервера, сравнения их с новыми данными, а затем отправки новых данных (если они не существуют) на API-сервер.В настоящее время я работаю над функциональностью получения существующих данных на сервере, используя $ http, promises и $ q.all ().Когда я помещаю все обещания в массив и затем использую $ q.all (), он запускается синхронно и не ждет разрешения обещаний.

Я уже прошел и, насколько мне известно, вложил возврат во все операции, которые я хочу выполнить асинхронно.Я также прочитал много постов с похожими проблемами и внес эти коррективы безуспешно.

Это соответствующий код из службы fileData:

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

и код используемого контроллера:

$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;
};  

Что мне нужновидно, что результаты тестов возвращаются, тест помещается в соответствующий массив, а затем $ q.all () разрешается, чтобы можно было сравнивать новые и существующие данные.На самом деле происходит то, что внутренние обещания разрешаются, $ q.all () разрешается, а вложенный цикл for не запускается, потому что в массиве нет значений.

1 Ответ

0 голосов
/ 03 января 2019

Во-первых, я бы начал с избавления от 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);
   });

});
...