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.