多次API调用后的角度执行函数

时间:2016-11-19 22:51:59

标签: javascript angularjs api asynchronous promise

我正在编写一个角色服务来进行一些http调用。 代码是这样的。

this.checkAndSendNotifications = function() {

UsersService.getArray(function(array) {

    var notifications = [];
    angular.forEach(array, function(element) {

        if (some conditions is true) {
            srv.sendNotificationToToken(element.id,
                function() {
                    notifications.push({
                        id: user.id,
                        errorStatus: null,
                        errorStatusText: null
                    });
                },
                function(error) {
                    notifications.push({
                        id: user.id,
                        errorStatus: error.status,
                        errorStatusText: error.statusText
                    });
                });
        }

    });
    printNotificationsStatus(notifications);
 });
};

this.sendNotificationToToken = function(id, onSuccess, onError) {
    $http({
        method: 'POST',
        url: 'https://url....',
        headers: {
            'Authorization': 'Bearer ....',
            'Content-Type': 'application/json'
        },
        data: {
            "id": id,
            "message": "hello"
        }
    }).then(function successCallback(response) {
        onSuccess();
    }, function errorCallback(error) {
        onError(error)
    });
};

我只需要在所有api调用结束时调用printNotificationsStatus()函数,以确保所有api响应,但现在函数在angular.forEach执行结束时被调用,API的承诺可以在以后解决因为它们是同步的。

有没有办法等待?

提前致谢 的Davide

2 个答案:

答案 0 :(得分:2)

您可以使用$q.all等待所有承诺得到解决。像这样:

UsersService.getArray(function(array) {

    var promises = [];
    var notifications = [];
    angular.forEach(array, function(element) {

        if (some conditions is true) {
            var promise = srv.sendNotificationToToken(element.id,
                function() {
                    notifications.push({
                        id: user.id,
                        errorStatus: null,
                        errorStatusText: null
                    });
                },
                function(error) {
                    notifications.push({
                        id: user.id,
                        errorStatus: error.status,
                        errorStatusText: error.statusText
                    });
                });
            promises.push(promise);
        }

    });

    // wait all promises and resolve
    $q.all(promises).then(function () {
        printNotificationsStatus(notifications);    
    })

 });
};
不要忘记注入$ q。

Ps:在你的代码中,你在第一次迭代后执行printNotificationsStatus()。

答案 1 :(得分:2)

首先,我注意到您在foreach中呼叫printNotificationsStatus,因此它将作为阵列中的项目被调用多次。如果这是一个同步过程,它只需要超出forEach。

但是你在forEach中进行异步调用。 这意味着"主要"线程或执行不会等待每个sendNotificationToToken的响应。

javascript中存在一些针对此类问题的好模式。 我认为最常见的是@Bruno Pares建议:https://stackoverflow.com/a/40698868/957979

Async库也是一个不错的选择。

但是当您正在使用回调时,您可以重新构建代码以跟踪实际迭代,并且在完成后,您可以调用printNotificationsStatus 这个答案我觉得完全适用于你所要求的。 https://stackoverflow.com/a/18983245/957979 [提及链接的代码]:

function callback () { console.log('all done'); }

var itemsProcessed = 0;

[1, 2, 3].forEach((item, index, array) => {
  asyncFunction(item, () => {
    itemsProcessed++;
    if(itemsProcessed === array.length) {
      callback();
    }
  });
});