From 204eb57a3b933f2d7dcb85cc3b1e938b7d333abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Bischoff?= Date: Tue, 12 Dec 2023 09:57:46 +0100 Subject: [PATCH] feat: add option to run parallel in order --- docs/async/parallel.mdx | 15 ++++++++++++++- src/async.ts | 5 +++-- src/tests/async.test.ts | 20 +++++++++++++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/async/parallel.mdx b/docs/async/parallel.mdx index 37cd9c99..fc042dac 100644 --- a/docs/async/parallel.mdx +++ b/docs/async/parallel.mdx @@ -25,10 +25,23 @@ const users = await parallel(3, userIds, async (userId) => { }) ``` +By default `parallel` will pick from the array in reverse order. +If you want to run the functions in the order they are in the array +you can pass `executeInOrder` option in the 4th argument. + +```ts +// Will run the find user async function 3 at a time +// starting at the beginning of the array +const users = await parallel(3, userIds, async (userId) => { + return await api.users.find(userId) +}, {executeInOrder: true}) +``` + + ## Errors When all work is complete parallel will check for errors. If any -occurred they will all be thrown in a single `AggregateError` that +occurred they will all be thrown in a single `AggregateError` that has an `errors` property that is all the errors that were thrown. ```ts diff --git a/src/async.ts b/src/async.ts index 72864df0..c90dd853 100644 --- a/src/async.ts +++ b/src/async.ts @@ -112,7 +112,8 @@ export class AggregateError extends Error { export const parallel = async ( limit: number, array: readonly T[], - func: (item: T) => Promise + func: (item: T) => Promise, + options?: { executeInOrder?: boolean } ): Promise => { const work = array.map((item, index) => ({ index, @@ -122,7 +123,7 @@ export const parallel = async ( const processor = async (res: (value: WorkItemResult[]) => void) => { const results: WorkItemResult[] = [] while (true) { - const next = work.pop() + const next = options?.executeInOrder ? work.shift() : work.pop() if (!next) return res(results) const [error, result] = await tryit(func)(next.item) results.push({ diff --git a/src/tests/async.test.ts b/src/tests/async.test.ts index e67aa3d0..e2ed600c 100644 --- a/src/tests/async.test.ts +++ b/src/tests/async.test.ts @@ -330,7 +330,7 @@ describe('async module', () => { assert.isUndefined(errors) assert.deepEqual(results, ['hi_1', 'hi_2', 'hi_3']) }) - test('throws erros as array of all errors', async () => { + test('throws errors as array of all errors', async () => { const [error, results] = await _.try(async () => { return _.parallel(1, _.list(1, 3), async num => { await _.sleep(1000) @@ -354,6 +354,24 @@ describe('async module', () => { }) assert.deepEqual(Math.max(...tracking), 3) }) + test('execute in reverse order', async () => { + let numInProgress = 0 + const tracking: number[] = [] + await _.parallel(1, _.list(1, 4), async (num) => { + tracking.push(num) + await _.sleep(10) + }) + assert.deepEqual(tracking, [4, 3, 2, 1]); + }) + test('execute in order', async () => { + let numInProgress = 0 + const tracking: number[] = [] + await _.parallel(1, _.list(1, 4), async (num) => { + tracking.push(num) + await _.sleep(10) + }, {executeInOrder: true}) + assert.deepEqual(tracking, [1, 2, 3, 4]); + }) }) describe('_.retry', () => {