What is neo-async?
The neo-async package is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript. It is similar to the async package but with some performance improvements.
What are neo-async's main functionalities?
Control Flow
Execute a series of functions in sequential order. Each function is passed a callback it must call on completion.
async.series([
function(callback) {
// do some stuff ...
callback(null, 'one');
},
function(callback) {
// do some more stuff ...
callback(null, 'two');
}
],
function(err, results) {
// results is now equal to ['one', 'two']
});
Collections
Apply a function to each item in a collection and collect the results.
async.map(['file1','file2','file3'], fs.stat, function(err, results) {
// results is now an array of stats for each file
});
Utilities
Call a function a certain number of times and collect the results.
async.times(5, function(n, next) {
createUser(n, function(err, user) {
next(err, user);
});
}, function(err, users) {
// we should now have 5 users
});
Other packages similar to neo-async
async
The original async package offers a wide array of functions for working with asynchronous code. Neo-async claims to offer similar functionality with improved performance.
bluebird
Bluebird is a full-featured promise library with a focus on innovative features and performance. It can be used as an alternative to neo-async for handling asynchronous operations using promises instead of callbacks.
q
Q is a tool for making and composing asynchronous promises in JavaScript. It's an older promise library that can serve similar purposes to neo-async but with a different style of handling async operations.
Neo-Async
Neo-Async is faster than Async.js and has more feature.
$ npm install neo-async
Speed Comparison
Results
- series
- parallel
- waterfall
Common
var _ = require('lodash');
var async = require('async');
var neo_async = require('neo-async');
var start = function() {
return process.hrtime();
};
var getDiff = function(start) {
var diff = process.hrtime(start);
return diff[0] * 1e9 + diff[1];
};
var sample = 1000;
var time = {
async: 0,
neo_async: 0
};
series
var tasks = _.map(_.times(sample), function(item) {
return function(callback) {
callback(null, item);
};
});
var timer = start();
async.series(tasks, function(err, res1) {
time.async = getDiff(timer);
timer = start();
neo_async.series(tasks, function(err, res2) {
time.neo_async = getDiff(timer);
var check = _.every(res1, function(item, index) {
return res2[index] === item;
});
console.log('check', check);
console.log('**** time ****');
console.log(time.async - time.neo_async);
});
});
- async, neo_asyncの順
- { async: 2632607, neo_async: 1097360 }
- 1.5ms短縮 (1535247ns)
- neo_sync, asyncの順
- { async: 3749187, neo_async: 1615040 }
- 2.1ms短縮 (2134147ns)
parallel
var tasks = _.map(_.times(sample), function(item) {
return function(callback) {
callback(null, item);
};
});
var timer = start();
neo_async.parallel(tasks, function(err, res1) {
time.neo_async = getDiff(timer);
timer = start();
async.parallel(tasks, function(err, res2) {
time.async = getDiff(timer);
var check = _.every(res1, function(item, index) {
return res2[index] === item;
});
console.log('check', check);
console.log('**** time ****');
console.log(time.async - time.neo_async);
});
});
- async, neo_asyncの順
- { async: 3291565, neo_async: 1166516 }
- 2.1ms短縮 (2125049ns)
- neo_sync, asyncの順
- { async: 3326372, neo_async: 1174852 }
- 2.1ms短縮 (2151520ns)
waterfall
var tasks = (function createSimpleTasks(num) {
var first = true;
var tasks = _.transform(_.times(num), function(memo, num, key) {
if (first) {
first = false;
memo[key] = function(done) {
done(null, num);
};
} else {
memo[key] = function(sum, done) {
done(null, sum + num);
};
}
});
return tasks;
})(sample);
var timer = start();
async.waterfall(tasks, function(err, res1) {
time.neo_async = getDiff(timer);
timer = start();
async.waterfall(tasks, function(err, res2) {
time.async = getDiff(timer);
console.log('check', res1 === res2);
console.log('**** time ****');
console.log(time.async - time.neo_async);
});
});
- async, neo_asyncの順
- { async: 11875267, neo_async: 3183565 }
- 8.7ms短縮 (8691702ns)
- neo_sync, asyncの順
- { async: 11667079, neo_async: 2760822 }
- 8.9ms短縮 (8906257ns)
Feature
Collections
- async.each [Series, Limit]
- async.map [Series, Limit]
- async.filter [Series, Limit]
- async.reject [Series, Limit]
- async.detect [Series, Limit]
- async.pick [Series, Limit]
- async.transform [Series, Limit]
- async.reduce
- async.reduceRight
- async.sortBy [Series, Limit]
- async.some [Series, Limit]
- async.every [Series, Limit]
- async.concat [Series, Limit]
Control Flow
- async.series
- async.parallel [Limit]
- async.waterfall
- async.whilst
- async.doWhilst
- async.until
- async.doUntil
- async.forever
- async.seq
- async.applyEach [Series]
- async.queue
- async.priorityQueue
- async.cargo
- async.auto
- async.retry
- async.iterator
- async.nextTick
- async.setImmediate
- async.times [Series, Limit]
Utils
- async.memoize
- async.unmemoize
- async.log
- async.dir
- async.noConflict