Javascript 在多次API调用后执行函数

Javascript 在多次API调用后执行函数,javascript,angularjs,api,asynchronous,promise,Javascript,Angularjs,Api,Asynchronous,Promise,我正在编写一个angular服务来进行一些http调用。 代码是这样的 this.checkAndSendNotifications = function() { UsersService.getArray(function(array) { var notifications = []; angular.forEach(array, function(element) { if (some conditions is true) {

我正在编写一个angular服务来进行一些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

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

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()。

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

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()。

首先,我注意到您在foreach中调用了
printNotificationsStatus
,因此它将被调用的次数与数组中的项相同。如果这是一个同步过程,那么它只需要在forEach之外

但是您正在forEach中进行异步调用。 这意味着“主”线程或执行不会等待每个
sendNotificationToToToToToken
的响应

对于javascript中的这类问题,有几种很好的模式。 我认为最常见的是@Bruno Pares建议的:

异步库也是一个不错的选择

但是使用当前使用的回调,您可以重新构造代码以跟踪实际的迭代,并且在完成之后,您可以调用
printNotificationsStatus
我认为这个答案完全适用于你的问题。 [所述链接中的代码]:

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

var itemsProcessed = 0;

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

首先,我注意到您在foreach中调用了
printNotificationsStatus
,因此它将被调用的次数与数组中的项相同。如果这是一个同步过程,那么它只需要在forEach之外

但是您正在forEach中进行异步调用。 这意味着“主”线程或执行不会等待每个
sendNotificationToToToToToken
的响应

对于javascript中的这类问题,有几种很好的模式。 我认为最常见的是@Bruno Pares建议的:

异步库也是一个不错的选择

但是使用当前使用的回调,您可以重新构造代码以跟踪实际的迭代,并且在完成之后,您可以调用
printNotificationsStatus
我认为这个答案完全适用于你的问题。 [所述链接中的代码]:

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

var itemsProcessed = 0;

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

看看
$q.all([承诺…])
。您需要您的服务返回一个承诺,这样您就可以将它们推送到阵列中。正如Bruno和cesaregb注意到我在printNotificationsStatus位置上犯了一个错误。。。看看
$q.all([承诺…])
。您需要您的服务返回一个承诺,这样您就可以将它们推送到阵列中。正如Bruno和cesaregb注意到我在printNotificationsStatus位置上犯了一个错误。。。坦克