code: function all(promises) {
      var deferred = new Deferred(),
          counter = 0,
          results = isArray(promises) ? [] : {};
  
      forEach(promises, function(promise, key) {
        counter++;
        when(promise).then(function(value) {
          if (results.hasOwnProperty(key)) return;
          results[key] = value;
          if (!(--counter)) deferred.resolve(results);
        }, function(reason) {
          if (results.hasOwnProperty(key)) return;
          deferred.reject(reason);
        });
      });
  
      if (counter === 0) {
        deferred.resolve(results);
      }
  
      return deferred.promise;
    }
docs: @ngdoc method
  @name $q#all
  @kind function
  
  @description
  Combines multiple promises into a single promise that is resolved when all of the input
  promises are resolved.
  
  @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
  @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
  each value corresponding to the promise at the same index/key in the `promises` array/hash.
  If any of the promises is resolved with a rejection, this resulting promise will be rejected
  with the same rejection value.