Skip to content

Commit

Permalink
add arr.async
Browse files Browse the repository at this point in the history
  • Loading branch information
ajmnz committed Nov 14, 2024
1 parent ef0f160 commit 242a518
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 25 deletions.
87 changes: 67 additions & 20 deletions src/array.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { prom } from ".";

/**
* Remove duplicates from an array without using Set or mutating the provided
* array.
Expand Down Expand Up @@ -47,24 +45,6 @@ export const dupes = <T>(
})
);

/**
* Like `Array.map`, but async and awaited sequentially using `prom.seq`.
*
* @param arr - The target array
* @param cb - Map callback
* @returns The result
* @example
* ```ts
* const [e1, e2, e3] = arr.mapAsync(["foo", "bar", "baz"], async (e) => await myFn(e));
* ```
*/
export const mapAsync = async <T, U>(
arr: T[],
cb: (value: T, index: number, array: T[]) => Promise<U>
): Promise<U[]> => {
return await prom.seq(arr.map(cb));
};

/**
* Try to get the first value from an array.
*
Expand Down Expand Up @@ -227,3 +207,70 @@ export const shuffle = <T extends any[]>(array: T): T => {

return shuffled;
};

//
// Async items
//

/**
* Like `Array.map`, but async and awaited using `Promise.all`.
*
* @param arr - The target array
* @param cb - Map callback
* @returns The result
* @example
* ```ts
* const [e1, e2, e3] = await arr.async.map(["foo", "bar", "baz"], async (e) => await myFn(e));
* ```
*/
const asyncMap = async <T, U>(
arr: T[],
cb: (value: T, index: number, array: T[]) => Promise<U>
) => await Promise.all(arr.map(cb));

/**
* Like `Array.flatMap`, but with an async callback.
*
* @param arr - The target array
* @param cb - FlatMap callback
* @returns The result
* @example
* ```ts
* const v = arr.async.flatMap(["foo", "bar", "baz"], async (e) => await myFn(e));
* ```
*/
const asyncFlatmap = async <T, U>(
arr: T[],
cb: (value: T, index: number, array: T[]) => Promise<U>
) => (await Promise.all(arr.map(cb))).flat();

/**
* Like `Array.filter`, but with an async callback.
*
* @param arr - The target array
* @param cb - Filter callback
* @returns The result
* @example
* ```ts
* const v = arr.async.filter(["foo", "bar", "baz"], async (e) => await myFn(e));
* ```
*/
const asyncFilter = async <T>(
arr: T[],
cb: (value: T, index: number, array: T[]) => Promise<unknown>
) => {
const e: T[] = [];
for (let i = 0; i < arr.length; i++) {
const v = arr[i];
if (await cb(v, i, arr)) {
e.push(v);
}
}
return e;
};

export const async = {
map: asyncMap,
flatMap: asyncFlatmap,
filter: asyncFilter,
};
27 changes: 22 additions & 5 deletions test/arr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ describe("arr", () => {
).toEqual([[1, 2]]);
});

test("mapAsync", async () => {
const e = [1, 2, 3, 4];
expect(await arr.mapAsync(e, (v) => Promise.resolve(v + 1))).toEqual([2, 3, 4, 5]);
});

test("first", () => {
expect(arr.first([1, 2, 3])).toEqual(1);
expect(arr.first([1])).toEqual(1);
Expand Down Expand Up @@ -125,4 +120,26 @@ describe("arr", () => {
expect(arr.shuffle([])).toEqual([]);
expect(arr.shuffle([1])).toEqual([1]);
});

describe("async", () => {
test("map", async () => {
const e = [1, 2, 3, 4];
// eslint-disable-next-line require-await
expect(await arr.async.map(e, async (v) => v + 1)).toEqual([2, 3, 4, 5]);
});

test("flatMap", async () => {
expect(
// eslint-disable-next-line require-await
await arr.async.flatMap([1, 2, 3], async (v) => (v === 1 ? [] : v))
).toEqual([2, 3]);
});

test("filter", async () => {
expect(
// eslint-disable-next-line require-await
await arr.async.filter([1, 2, 3], async (v) => v !== 1)
).toEqual([2, 3]);
});
});
});

0 comments on commit 242a518

Please sign in to comment.