| 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; |
| } |