function all(promises) {
    var deferred = defer(),
        counter = promises.length,
        results = [];

    if (counter) {
      forEach(promises, function(promise, index) {
        ref(promise).then(function(value) {
          if (index in results) return;
          results[index] = value;
          if (!(--counter)) deferred.resolve(results);
        }, function(reason) {
          if (index in results) return;
          deferred.reject(reason);
        });
      });
    } else {
      deferred.resolve(results);
    }

    return deferred.promise;
  }
@ngdoc
@name angular.module.ng.$q#all
@methodOf angular.module.ng.$q
@description
Combines multiple promises into a single promise that is resolved when all of the input
promises are resolved.

@param {Array.<Promise>} promises An array of promises.
@returns {Promise} Returns a single promise that will be resolved with an array of values,
  each value coresponding to the promise at the same index in the `promises` array. If any of
  the promises is resolved with a rejection, this resulting promise will be resolved with the
  same rejection.