• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1var async = require('./async.js')
2  , abort = require('./abort.js')
3  ;
4
5// API
6module.exports = iterate;
7
8/**
9 * Iterates over each job object
10 *
11 * @param {array|object} list - array or object (named list) to iterate over
12 * @param {function} iterator - iterator to run
13 * @param {object} state - current job status
14 * @param {function} callback - invoked when all elements processed
15 */
16function iterate(list, iterator, state, callback)
17{
18  // store current index
19  var key = state['keyedList'] ? state['keyedList'][state.index] : state.index;
20
21  state.jobs[key] = runJob(iterator, key, list[key], function(error, output)
22  {
23    // don't repeat yourself
24    // skip secondary callbacks
25    if (!(key in state.jobs))
26    {
27      return;
28    }
29
30    // clean up jobs
31    delete state.jobs[key];
32
33    if (error)
34    {
35      // don't process rest of the results
36      // stop still active jobs
37      // and reset the list
38      abort(state);
39    }
40    else
41    {
42      state.results[key] = output;
43    }
44
45    // return salvaged results
46    callback(error, state.results);
47  });
48}
49
50/**
51 * Runs iterator over provided job element
52 *
53 * @param   {function} iterator - iterator to invoke
54 * @param   {string|number} key - key/index of the element in the list of jobs
55 * @param   {mixed} item - job description
56 * @param   {function} callback - invoked after iterator is done with the job
57 * @returns {function|mixed} - job abort function or something else
58 */
59function runJob(iterator, key, item, callback)
60{
61  var aborter;
62
63  // allow shortcut if iterator expects only two arguments
64  if (iterator.length == 2)
65  {
66    aborter = iterator(item, async(callback));
67  }
68  // otherwise go with full three arguments
69  else
70  {
71    aborter = iterator(item, key, async(callback));
72  }
73
74  return aborter;
75}
76