Async Each is an ultra-simple, lightweight JavaScript library that provides asynchronous parallel iteration over arrays. It offers a no-bullshit, 35-lines-of-code solution for processing arrays concurrently with error handling and result transformation, without the overhead of larger async libraries.
npm install async-eachconst each = require('async-each');For AMD (RequireJS):
define(['async-each'], function(each) {
// use each
});For browser (global):
// Available as window.asyncEach
asyncEach(array, iterator, callback);const each = require('async-each');
const fs = require('fs');
// Process files in parallel
each(['file1.txt', 'file2.txt', 'file3.txt'], fs.readFile, function(error, contents) {
if (error) {
console.error('Error reading files:', error);
return;
}
console.log('File contents:', contents);
});
// Transform data in parallel
each([1, 2, 3, 4, 5], function(item, done) {
// Simulate async operation
setTimeout(() => {
done(null, item * 2);
}, 100);
}, function(error, results) {
if (error) {
console.error('Error:', error);
return;
}
console.log('Results:', results); // [2, 4, 6, 8, 10]
});Processes array items asynchronously in parallel, maintaining original array order in results.
/**
* Asynchronous parallel forEach function for arrays
* @param items - Array of items to process
* @param next - Iterator function called for each item
* @param callback - Optional completion callback
*/
function each(items, next, callback);Parameters:
Array, required): Array of items to process. Must be an array, throws TypeError if not.Function, required): Iterator function called for each item. Signature: next(item, done)
item: Current array item being processeddone: Callback function with signature done(error, transformedItem)
error: Error value (any truthy value treated as error)transformedItem: Optional transformed result for this itemFunction, optional): Completion callback. Signature: callback(error, results)
error: Error object if any iteration failed, undefined on successresults: Array of transformed items in original orderBehavior:
undefined (no return value)Error Handling:
TypeError if items is not an arrayTypeError if next is not a functionError object if any iterator returns an errornew Error() constructorUsage Examples:
const each = require('async-each');
// File processing example
each(['config.json', 'data.json'], require('fs').readFile, function(error, files) {
if (error) return console.error(error);
console.log('Loaded files:', files.map(f => f.toString()));
});
// Data transformation example
each(['hello', 'world'], function(item, done) {
done(null, item.toUpperCase());
}, function(error, results) {
console.log(results); // ['HELLO', 'WORLD']
});
// Error handling example
each([1, 2, 3], function(item, done) {
if (item === 2) {
done('Error processing item 2');
} else {
done(null, item * 10);
}
}, function(error, results) {
if (error) {
console.error('Processing failed:', error); // "Error processing item 2"
}
});
// Without callback (fire and forget)
each([1, 2, 3], function(item, done) {
console.log('Processing:', item);
done(null, item);
});For TypeScript users, the effective type definitions are:
type IteratorFunction<T, R> = (
item: T,
done: (error?: any, result?: R) => void
) => void;
type CompletionCallback<R> = (
error?: Error,
results?: R[]
) => void;
function each<T, R>(
items: T[],
next: IteratorFunction<T, R>,
callback?: CompletionCallback<R>
): void;module.exports)window.asyncEachimport each from 'async-each')Common error scenarios and handling:
const each = require('async-each');
// Invalid arguments
try {
each('not-an-array', function() {}, function() {});
} catch (error) {
console.error(error.message); // "each() expects array as first argument"
}
try {
each([], 'not-a-function', function() {});
} catch (error) {
console.error(error.message); // "each() expects function as second argument"
}
// Iterator error handling
each([1, 2, 3], function(item, done) {
if (item === 2) {
done('Custom error message');
} else {
done(null, item);
}
}, function(error, results) {
if (error) {
console.error('Error occurred:', error.message); // "Custom error message"
}
});