code: function reduce(coll, memo, iteratee, callback) {
      callback = once(callback);
      var _iteratee = wrapAsync(iteratee);
      return eachOfSeries(coll, (x, i, iterCb) => {
          _iteratee(memo, x, (err, v) => {
              memo = v;
              iterCb(err);
          });
      }, err => callback(err, memo));
  }
docs: Reduces `coll` into a single value using an async `iteratee` to return each
  successive step. `memo` is the initial state of the reduction. This function
  only operates in series.
  
  For performance reasons, it may make sense to split a call to this function
  into a parallel map, and then use the normal `Array.prototype.reduce` on the
  results. This function is for situations where each step in the reduction
  needs to be async; if you can get the data before reducing it, then it's
  probably a good idea to do so.
  
  @name reduce
  @static
  @memberOf module:Collections
  @method
  @alias inject
  @alias foldl
  @category Collection
  @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
  @param {*} memo - The initial state of the reduction.
  @param {AsyncFunction} iteratee - A function applied to each item in the
  array to produce the next step in the reduction.
  The `iteratee` should complete with the next state of the reduction.
  If the iteratee complete with an error, the reduction is stopped and the
  main `callback` is immediately called with the error.
  Invoked with (memo, item, callback).
  @param {Function} [callback] - A callback which is called after all the
  `iteratee` functions have finished. Result is the reduced value. Invoked with
  (err, result).
  @returns {Promise} a promise, if no callback is passed
  @example
  
  async.reduce([1,2,3], 0, function(memo, item, callback) {
  // pointless async:
  process.nextTick(function() {
  callback(null, memo + item)
  });
  }, function(err, result) {
  // result is now equal to the last value of memo, which is 6
  });