76 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			76 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								var async = require('./async.js')
							 | 
						||
| 
								 | 
							
								  , abort = require('./abort.js')
							 | 
						||
| 
								 | 
							
								  ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// API
							 | 
						||
| 
								 | 
							
								module.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;
							 | 
						||
| 
								 | 
							
								}
							 |