AngularJS:$ q等待所有人,即使1被拒绝

Zen*_*uka 28 angularjs

我一直试图等待Angular的$ q的几个承诺,但似乎没有选择'等待所有即使被拒绝的承诺'.我创建了一个例子(http://jsfiddle.net/Zenuka/pHEf9/21/),我希望在所有承诺被解决/拒绝时执行一个函数,这可能吗?就像是:

$q.whenAllComplete(promises, function() {....})
Run Code Online (Sandbox Code Playgroud)

编辑:在示例中,您看到第二个服务失败,并且在此之后立即$q.all().then(..., function(){...})执行函数.我想等待第五个承诺完成.

Zen*_*uka 30

好吧,我自己实现了一个基本版本(我只想等待一系列的承诺).任何人都可以扩展这个或创建一个更清洁的版本,如果他们想:-)检查jsfiddle以查看它在行动:http://jsfiddle.net/Zenuka/pHEf9/

angular.module('test').config(['$provide', function ($provide) {
    $provide.decorator('$q', ['$delegate', function ($delegate) {
        var $q = $delegate;

        // Extention for q
        $q.allSettled = $q.allSettled || function (promises) {
            var deferred = $q.defer();
            if (angular.isArray(promises)) {
                var states = [];
                var results = [];
                var didAPromiseFail = false;
                if (promises.length === 0) { 
                    deferred.resolve(results);
                    return deferred.promise;
                }

                // First create an array for all promises with their state
                angular.forEach(promises, function (promise, key) {
                    states[key] = false;
                });

                // Helper to check if all states are finished
                var checkStates = function (states, results, deferred, failed) {
                    var allFinished = true;
                    angular.forEach(states, function (state, key) {
                        if (!state) {
                            allFinished = false;
                        }
                    });
                    if (allFinished) {
                        if (failed) {
                            deferred.reject(results);
                        } else {
                            deferred.resolve(results);
                        }
                    }
                }

                // Loop through the promises
                // a second loop to be sure that checkStates is called when all states are set to false first
                angular.forEach(promises, function (promise, key) {
                    $q.when(promise).then(function (result) {
                        states[key] = true;
                        results[key] = result;
                        checkStates(states, results, deferred, didAPromiseFail);
                    }, function (reason) {
                        states[key] = true;
                        results[key] = reason;
                        didAPromiseFail = true;
                        checkStates(states, results, deferred, didAPromiseFail);
                    });
                });
            } else {
                throw 'allSettled can only handle an array of promises (for now)';
            }

            return deferred.promise;
        };

        return $q;
    }]);
}]);
Run Code Online (Sandbox Code Playgroud)


Mic*_*pat 18

类似于如何all()返回已解析值的数组/散列,Kris Kowal的Q allSettled()函数返回一组对象,其外观如下:

{ state: 'fulfilled', value: <resolved value> }
Run Code Online (Sandbox Code Playgroud)

要么:

{ state: 'rejected', reason: <rejection error> }
Run Code Online (Sandbox Code Playgroud)

由于这种行为非常方便,我已将该函数移植到Angular.js的$ q:

angular.module('your-module').config(['$provide', function ($provide) {
    $provide.decorator('$q', ['$delegate', function ($delegate) {
        var $q = $delegate;

        $q.allSettled = $q.allSettled || function allSettled(promises) {
            // Implementation of allSettled function from Kris Kowal's Q:
            // https://github.com/kriskowal/q/wiki/API-Reference#promiseallsettled

            var wrapped = angular.isArray(promises) ? [] : {};

            angular.forEach(promises, function(promise, key) {
                if (!wrapped.hasOwnProperty(key)) {
                    wrapped[key] = wrap(promise);
                }
            });

            return $q.all(wrapped);

            function wrap(promise) {
                return $q.when(promise)
                    .then(function (value) {
                        return { state: 'fulfilled', value: value };
                    }, function (reason) {
                        return { state: 'rejected', reason: reason };
                    });
            }
        };

        return $q;
    }]);
}]);
Run Code Online (Sandbox Code Playgroud)

归功于: