0

I'm currently using two approaches to parallelize the execution of async functions in JavaScript Node.js. I do not intend to find which of the Promise or callback approach is best, but I'm likely searching for a better approach to parallelize functions execution in Node.js without using child_process.fork(), so that it can be used in the same process.

Assumed that my functions are Promise, hence a typical function will be like

var myFunc = () => new Promise((resolve, reject) => {
  setTimeout(() => resolve("some task"), 500)
})
myFunc().then(_ => console.log(_)).catch(err => console.err(err))

One approach is using Promise.all in this way:

var promiseAllP = function(items, block) {
  var promises = [];
  items.forEach(function(item, index) {
    promises.push(function(item, i) {
      return new Promise(function(resolve, reject) {
        return block.apply(this, [item, index, resolve, reject]);
      });
    }(item, index))
  });
  return Promise.all(promises);
} //promiseAll
promiseAllP([...Array(3).keys()], (item, index, resolve, reject) => {
    setTimeout(() => resolve("task "+index), 500 * index)
  })
  .then(_ => console.log(_)).catch(err => console.err(err))

the other approach would be using async execution with a callback like

var tasks = [
  (cb) => setTimeout(() => cb(null, "task 1"), 500 * 1),
  (cb) => setTimeout(() => cb(null, "task 2"), 500 * 2),
  (cb) => setTimeout(() => cb(null, "task 3"), 500 * 3),
];

function parallel(tasks, cb) {
  var results, pending, keys
  var isSync = true

  if (Array.isArray(tasks)) {
    results = []
    pending = tasks.length
  } else {
    keys = Object.keys(tasks)
    results = {}
    pending = keys.length
  }

  function done(err) {
    function end() {
      if (cb) cb(err, results)
      cb = null
    }
    if (isSync) process.nextTick(end)
    else end()
  }

  function each(i, err, result) {
    results[i] = result
    if (--pending === 0 || err) {
      done(err)
    }
  }

  if (!pending) {
    // empty
    done(null)
  } else if (keys) {
    // object
    keys.forEach(function(key) {
      tasks[key](function(err, result) {
        each(key, err, result)
      })
    })
  } else {
    // array
    tasks.forEach(function(task, i) {
      task(function(err, result) {
        each(i, err, result)
      })
    })
  }

  isSync = false
}

parallel(tasks, (err, res) => {
  if (err) console.error(error)
  else console.log(res)
});

The last one can be easily adapted to support Promise instead of callback. The problem is that I didn't find any improvement in executing my tasks through the first approach or the second one, so which is the best solution among them or is out of there a better approach to execute parallel tasks without using Node.js child_process.fork()?

The tasks to run have different execution times, they do not share memory, and I can run a callback or Promise.resolve to notify the caller that the task ended gracefully or Promise.reject if some error occurred.

loretoparisi
  • 15,724
  • 11
  • 102
  • 146
  • So the fact that second snippet is several times bigger than first one isn't enough, is it? The question is basically promises vs plain callbacks. I'm not sure why `promiseAllP` deal with callbacks as well. – Estus Flask Nov 02 '18 at 17:41
  • 1
    They are doing the same. Just, as you probably see, the code with `Promise`-s is simpler. That is what `Promise`-s are for: wrapping callbacks in a nice, compact way. Any kind of parallelism is independent from them and happening inside the engine: on the JavaScript level both constructs are single threaded and one piece of JS code is running at a time. – tevemadar Nov 02 '18 at 17:54
  • 1
    Possible duplicate of [Node.js: When to use Promises vs Callbacks](https://stackoverflow.com/questions/45041462/node-js-when-to-use-promises-vs-callbacks) – tevemadar Nov 02 '18 at 17:54
  • @tevemadar I have detailed my question, because I'm most likely searching for a better way to execute more tasks in parallel, rather than a comparison between Promise and callback. thanks – loretoparisi Nov 02 '18 at 19:09

0 Answers0