Skip to content

Commit d195be5

Browse files
authored
Merge pull request #2 from GuthrieW/add-async-functions
Add async functions
2 parents 7795c7e + 71ba15c commit d195be5

File tree

12 files changed

+191
-221
lines changed

12 files changed

+191
-221
lines changed

dist/index.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export { default as findIndex } from "./src/findIndex";
55
export { default as findLast } from "./src/findLast";
66
export { default as findLastIndex } from "./src/findLastIndex";
77
export { default as map } from "./src/map";
8-
export { default as mapParallel } from "./src/mapParallel";
98
export { default as reduce } from "./src/reduce";
109
export { default as reduceRight } from "./src/reduceRight";
1110
export { default as some } from "./src/some";

dist/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
return (mod && mod.__esModule) ? mod : { "default": mod };
44
};
55
Object.defineProperty(exports, "__esModule", { value: true });
6-
exports.some = exports.reduceRight = exports.reduce = exports.mapParallel = exports.map = exports.findLastIndex = exports.findLast = exports.findIndex = exports.find = exports.filter = exports.every = void 0;
6+
exports.some = exports.reduceRight = exports.reduce = exports.map = exports.findLastIndex = exports.findLast = exports.findIndex = exports.find = exports.filter = exports.every = void 0;
77
var every_1 = require("./src/every");
88
Object.defineProperty(exports, "every", { enumerable: true, get: function () { return __importDefault(every_1).default; } });
99
var filter_1 = require("./src/filter");
@@ -18,8 +18,6 @@ var findLastIndex_1 = require("./src/findLastIndex");
1818
Object.defineProperty(exports, "findLastIndex", { enumerable: true, get: function () { return __importDefault(findLastIndex_1).default; } });
1919
var map_1 = require("./src/map");
2020
Object.defineProperty(exports, "map", { enumerable: true, get: function () { return __importDefault(map_1).default; } });
21-
var mapParallel_1 = require("./src/mapParallel");
22-
Object.defineProperty(exports, "mapParallel", { enumerable: true, get: function () { return __importDefault(mapParallel_1).default; } });
2321
var reduce_1 = require("./src/reduce");
2422
Object.defineProperty(exports, "reduce", { enumerable: true, get: function () { return __importDefault(reduce_1).default; } });
2523
var reduceRight_1 = require("./src/reduceRight");

dist/src/map.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
/**
22
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map|MDN Documentation Array.prototype.map}
3+
* Optionally, you can batch your iterations to more efficiently await blocking iteratee function calls using the batchIterations and batchSize attributes on the options parameter.
34
*
45
* @static
56
* @since 1.0.0
67
* @param {T[]} array
78
* @param {(value: T, index: number) => Promise<V>} iteratee
9+
* @param {{ batchIterations: boolean; batchSize: number }} [options]
810
* @returns {Promise<V[]>}
911
* @example
1012
* const array = [1, 2, 3];
1113
* const doubledArray = await map(array, async (value) => value * 2);
1214
*/
13-
export default function map<T, V>(array: T[], iteratee: (value: T, index: number) => Promise<V>): Promise<V[]>;
15+
export default function map<T, V>(array: T[], iteratee: (value: T, index: number) => Promise<V>, options?: {
16+
batchIterations: boolean;
17+
batchSize: number;
18+
}): Promise<V[]>;

dist/src/map.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,65 @@ Object.defineProperty(exports, "__esModule", { value: true });
33
exports.default = map;
44
/**
55
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map|MDN Documentation Array.prototype.map}
6+
* Optionally, you can batch your iterations to more efficiently await blocking iteratee function calls using the batchIterations and batchSize attributes on the options parameter.
67
*
78
* @static
89
* @since 1.0.0
910
* @param {T[]} array
1011
* @param {(value: T, index: number) => Promise<V>} iteratee
12+
* @param {{ batchIterations: boolean; batchSize: number }} [options]
1113
* @returns {Promise<V[]>}
1214
* @example
1315
* const array = [1, 2, 3];
1416
* const doubledArray = await map(array, async (value) => value * 2);
1517
*/
16-
async function map(array, iteratee) {
18+
async function map(array, iteratee, options) {
1719
if (!Array.isArray(array) || !array?.length)
1820
return [];
21+
if (options?.batchIterations) {
22+
return await mapParallel(array, iteratee, options.batchSize);
23+
}
24+
else {
25+
return await mapSerial(array, iteratee);
26+
}
27+
}
28+
async function mapParallel(array, iteratee, batchSize) {
29+
const arrayWithIndexKeys = array.map((item, i) => {
30+
return {
31+
task: item,
32+
index: i,
33+
};
34+
});
35+
const effectiveMaxBatchSize = batchSize > array.length ? array.length : batchSize;
36+
const results = [];
37+
await Promise.all(Array(effectiveMaxBatchSize)
38+
.fill(undefined)
39+
.map(async () => {
40+
const resultsWithIndex = await takeAndCompleteFromQueueUntilDone(arrayWithIndexKeys, iteratee);
41+
resultsWithIndex.forEach((result) => {
42+
results[result.index] = result.result;
43+
});
44+
}));
45+
return results;
46+
}
47+
/**
48+
* take and complete tasks from a queue until that queue is empty.
49+
* @param {{ task: T; index: number }[]} array
50+
* @param {(value: T, index: number) => Promise<V>} iteratee
51+
*/
52+
async function takeAndCompleteFromQueueUntilDone(array, iteratee) {
53+
const item = array.shift();
54+
if (!item) {
55+
return [];
56+
}
57+
const completedTask = await iteratee(item.task, item.index);
58+
const followingCompletedTasks = await takeAndCompleteFromQueueUntilDone(array, iteratee);
59+
return followingCompletedTasks.concat({
60+
result: completedTask,
61+
index: item.index,
62+
});
63+
}
64+
async function mapSerial(array, iteratee) {
1965
const results = [];
2066
for (let index = 0; index < array.length; index++) {
2167
const element = array[index];

dist/src/mapParallel.d.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.

dist/src/mapParallel.js

Lines changed: 0 additions & 54 deletions
This file was deleted.

index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export { default as findIndex } from "./src/findIndex";
55
export { default as findLast } from "./src/findLast";
66
export { default as findLastIndex } from "./src/findLastIndex";
77
export { default as map } from "./src/map";
8-
export { default as mapParallel } from "./src/mapParallel";
98
export { default as reduce } from "./src/reduce";
109
export { default as reduceRight } from "./src/reduceRight";
1110
export { default as some } from "./src/some";

src/map.ts

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,95 @@
11
/**
22
* {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map|MDN Documentation Array.prototype.map}
3+
* Optionally, you can batch your iterations to more efficiently await blocking iteratee function calls using the batchIterations and batchSize attributes on the options parameter.
34
*
45
* @static
56
* @since 1.0.0
67
* @param {T[]} array
78
* @param {(value: T, index: number) => Promise<V>} iteratee
9+
* @param {{ batchIterations: boolean; batchSize: number }} [options]
810
* @returns {Promise<V[]>}
911
* @example
1012
* const array = [1, 2, 3];
1113
* const doubledArray = await map(array, async (value) => value * 2);
1214
*/
1315
export default async function map<T, V>(
1416
array: T[],
15-
iteratee: (value: T, index: number) => Promise<V>
17+
iteratee: (value: T, index: number) => Promise<V>,
18+
options?: { batchIterations: boolean; batchSize: number }
1619
): Promise<V[]> {
1720
if (!Array.isArray(array) || !array?.length) return [];
1821

22+
if (options?.batchIterations) {
23+
return await mapParallel(array, iteratee, options.batchSize);
24+
} else {
25+
return await mapSerial(array, iteratee);
26+
}
27+
}
28+
29+
async function mapParallel<T, V>(
30+
array: T[],
31+
iteratee: (value: T, index: number) => Promise<V>,
32+
batchSize: number
33+
): Promise<V[]> {
34+
const arrayWithIndexKeys = array.map((item, i) => {
35+
return {
36+
task: item,
37+
index: i,
38+
};
39+
});
40+
41+
const effectiveMaxBatchSize =
42+
batchSize > array.length ? array.length : batchSize;
43+
44+
const results: V[] = [];
45+
await Promise.all(
46+
Array(effectiveMaxBatchSize)
47+
.fill(undefined)
48+
.map(async () => {
49+
const resultsWithIndex = await takeAndCompleteFromQueueUntilDone(
50+
arrayWithIndexKeys,
51+
iteratee
52+
);
53+
54+
resultsWithIndex.forEach((result) => {
55+
results[result.index] = result.result;
56+
});
57+
})
58+
);
59+
60+
return results;
61+
}
62+
63+
/**
64+
* take and complete tasks from a queue until that queue is empty.
65+
* @param {{ task: T; index: number }[]} array
66+
* @param {(value: T, index: number) => Promise<V>} iteratee
67+
*/
68+
async function takeAndCompleteFromQueueUntilDone<T, V>(
69+
array: { task: T; index: number }[],
70+
iteratee: (value: T, index: number) => Promise<V>
71+
): Promise<{ result: V; index: number }[]> {
72+
const item = array.shift();
73+
if (!item) {
74+
return [];
75+
}
76+
77+
const completedTask = await iteratee(item.task, item.index);
78+
const followingCompletedTasks = await takeAndCompleteFromQueueUntilDone<T, V>(
79+
array,
80+
iteratee
81+
);
82+
83+
return followingCompletedTasks.concat({
84+
result: completedTask,
85+
index: item.index,
86+
});
87+
}
88+
89+
async function mapSerial<T, V>(
90+
array: T[],
91+
iteratee: (value: T, index: number) => Promise<V>
92+
): Promise<V[]> {
1993
const results: V[] = [];
2094
for (let index = 0; index < array.length; index++) {
2195
const element = array[index];

src/mapParallel.ts

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)