| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 | var async = require('./async.js')  , abort = require('./abort.js')  ;// APImodule.exports = iterate;/** * Iterates over each job object * * @param {array|object} list - array or object (named list) to iterate over * @param {function} iterator - iterator to run * @param {object} state - current job status * @param {function} callback - invoked when all elements processed */function iterate(list, iterator, state, callback){  // store current index  var key = state['keyedList'] ? state['keyedList'][state.index] : state.index;  state.jobs[key] = runJob(iterator, key, list[key], function(error, output)  {    // don't repeat yourself    // skip secondary callbacks    if (!(key in state.jobs))    {      return;    }    // clean up jobs    delete state.jobs[key];    if (error)    {      // don't process rest of the results      // stop still active jobs      // and reset the list      abort(state);    }    else    {      state.results[key] = output;    }    // return salvaged results    callback(error, state.results);  });}/** * Runs iterator over provided job element * * @param   {function} iterator - iterator to invoke * @param   {string|number} key - key/index of the element in the list of jobs * @param   {mixed} item - job description * @param   {function} callback - invoked after iterator is done with the job * @returns {function|mixed} - job abort function or something else */function runJob(iterator, key, item, callback){  var aborter;  // allow shortcut if iterator expects only two arguments  if (iterator.length == 2)  {    aborter = iterator(item, async(callback));  }  // otherwise go with full three arguments  else  {    aborter = iterator(item, key, async(callback));  }  return aborter;}
 |