【问题标题】:Angular execute function after multiple API call多个API调用后的角度执行功能
【发布时间】:2017-04-03 14:03:06
【问题描述】:

我正在编写一个 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 的承诺可以稍后解决因为它们是异步的。

有没有办法等待?

提前致谢 大卫

【问题讨论】:

  • 看看$q.all([promises...])docs.angularjs.org/api/ng/service/$q#all。你需要你的服务返回一个承诺,这样你就可以将它们推送到一个数组中。
  • Bruno 和 cesaregb 注意到我在 printNotificationsStatus 位置上犯了一个错误……坦克

标签: javascript angularjs api asynchronous promise


【解决方案1】:

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

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

在 javascript 中有几个很好的模式可以解决这类问题。 我认为最常见的是@Bruno Pares 建议:https://stackoverflow.com/a/40698868/957979

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

但是在你当前使用的回调中,你可以重构代码来跟踪实际的迭代,在完成之后,你可以调用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();
    }
  });
});

【讨论】:

    【解决方案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()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-07
      • 2020-08-17
      • 1970-01-01
      • 2018-11-04
      • 2020-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多