@tunnckocore/p-all
v0.2.0
Published
Map or loop through promises, promise-returning or async functions, serially or in parallel, based on Promise.all! Has a hooks system: start, beforeEach, afterEach, finish.
Downloads
85
Maintainers
Readme
@tunnckocore/p-all
Map or loop through promises, promise-returning or async functions, serially or in parallel, based on Promise.all! Has a hooks system: start, beforeEach, afterEach, finish.
For usage, check the tests for now. Coverage is 100%, as always in the past 10 years.
It's similar to Promise.all
, or Promise.allSettled
more specifically, but
enhanced with a hooks system and ability to pass custom mapping function. It
works for promises and async functions.
import { strict as assert } from 'node:assert';
import test from 'asia';
import { each, parallel, serial } from '@tunnckocore/p-all';
const delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
test('parallel - correct results and order', async () => {
const order = [];
const results = await parallel([
() => delay(3000).then((x) => order.push('a')), // 8
() => delay(300).then((x) => order.push('b')), // 2
() => delay(1000).then((x) => order.push('c')), // 5
() => delay(100).then((x) => order.push('d')), // 1
() =>
delay(2000).then((x) => {
order.push('e');
throw new Error('the "e" error');
}), // 6
() => delay(1500).then((x) => order.push('f')), // 7
() => delay(560).then((x) => order.push('g')), // 3
() => delay(880).then((x) => order.push('h')), // 4
]);
assert.deepEqual(results, [
{ status: 'fulfilled', value: 8, index: 0 },
{ status: 'fulfilled', value: 2, index: 1 },
{ status: 'fulfilled', value: 5, index: 2 },
{ status: 'fulfilled', value: 1, index: 3 },
{
status: 'rejected',
reason: results[4].reason, // well.. lol
index: 4,
},
{ status: 'fulfilled', value: 6, index: 5 },
{ status: 'fulfilled', value: 3, index: 6 },
{ status: 'fulfilled', value: 4, index: 7 },
]);
assert.deepEqual(order, ['d', 'b', 'g', 'h', 'c', 'f', 'e', 'a']);
});
test('serial - force run in series', async () => {
const fixture = [
() => delay(3000).then((x) => 'a'), // 8
() => delay(300).then((x) => 'b'), // 2
() => delay(1000).then((x) => 'c'), // 5
() => delay(100).then((x) => 'd'), // 1
() =>
delay(2000).then((x) => {
throw new Error('the "e" error');
}), // 6
() => delay(1500).then((x) => 'f'), // 7
() => delay(560).then((x) => 'g'), // 3
() => delay(880).then((x) => 'h'), // 4
];
const results = await each(fixture, { serial: true });
assert.deepEqual(
results.map((x) => x.value),
['a', 'b', 'c', 'd', undefined, 'f', 'g', 'h'],
);
const serialResults = await serial(fixture);
assert.deepEqual(
serialResults.map((x) => x.value),
['a', 'b', 'c', 'd', undefined, 'f', 'g', 'h'],
);
});
test('custom mapper() function', async () => {
const res = [];
const results = await serial(
[() => 3, 2, () => 5, () => 1, () => 4],
function mapper(item, index) {
res.push(item);
return index > 2 ? item : undefined;
},
);
assert.deepEqual(results, res);
});
API
each(iterable, mapper, options)
If mapper
is object, it's assumed options
.
Passing options.serial
is the same as serial
.
You can also pass options.args
- custom arguments passed to each function.
A hooks system:
- options.start
- options.beforeEach
- options.afterEach
- options.finish
parallel(iterable, mapper, options)
If mapper
is object, it's assumed options
.
serial(iterable, mapper, options)
If mapper
is object, it's assumed options
.
License
Apache-2.0, 2022