Как обрабатывать несколько задач async в angular.js?

Работа над песочницей для изучения angular.js Я столкнулся со следующим шаблоном в нескольких местах моего кода. Мне нужно запросить mongoDB в цикле. Насколько я понимаю, каждый вызов происходит в своей собственной асинхронной задаче. Как узнать, когда все задачи будут завершены?

Например, у меня есть массив состояний. Часто мне нужно установить someProperty для someNewValue для каждого из состояний. После обновления всех состояний я хотел бы назвать someFunction().

for (var i = 0; i < $scope.states.length; i++) {
    $scope.states[i].someProperty = someNewValue;
    $scope.states[i].$update({stateId: $scope.states[i].id}, function() {
        someFunction();
    });
}

Пока, единственный способ, которым я могу это сделать, - вызвать someFunction() каждый раз, когда каждое обновление будет успешным. Я знаю, что должен быть более умный и лучший способ сделать это.

Каким будет ваш подход?

Ответ 1

Promises и $q.all (ref) являются вашими друзьями.

Более подробно вам придется сделать обещание для каждого вызова (если сам вызов не возвращает его), нажмите их в массиве и вызовите $q.all(promises).then(allFinished). Наивный случай, когда $update() не возвращает обещание:

function callUpdate(x, promises) {
    var d = $q.defer();
    x.$update({stateId: $scope.states[i].id}, function() {
        someFunction();
        d.resolve(); // it may be appropriate to call resolve() before someFunction() depending on your case
    });
    promises.push(d.promise);
}

...

var promises = [];
for (var i = 0; i < $scope.states.length; i++) {
    $scope.states[i].someProperty = someNewValue;
    callUpdate($scope.states[i], promises);
}

$q.all(promises).then(function() {
    // called when all promises have been resolved successully
});

Причиной существования callUpdate() является инкапсуляция обработки отложенного объекта и возврат обещания.