Skip to content

Commit 56cb4ca

Browse files
authored
Merge pull request #89 from Sykander/async-reduce
Async reduce
2 parents 1df2e0c + 0821581 commit 56cb4ca

25 files changed

+315
-107
lines changed

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
"main": "src/index.js",
66
"types": "types/index.d.ts",
77
"scripts": {
8-
"test:type-definitions": "./node_modules/.bin/tsc test/typings.ts && node test/typings.js",
8+
"test:type-definitions": "tsc test/typings.ts && node test/typings.js",
99
"test:code-style": "npm run lint:check",
10-
"test:unit-tests": "./node_modules/.bin/mocha test/**/*.spec.js",
11-
"test:coverage-report": "./node_modules/.bin/nyc npm run test:unit-tests --silent",
12-
"test:coverage-check": "./node_modules/.bin/nyc check-coverage",
10+
"test:unit-tests": "mocha test/**/*.spec.js",
11+
"test:coverage-report": "nyc npm run test:unit-tests --silent",
12+
"test:coverage-check": "nyc check-coverage",
1313
"test:coverage": "npm run test:coverage-report; npm run test:coverage-check",
1414
"test": "npm run test:unit-tests && npm run test:code-style && npm run test:type-definitions && npm run test:coverage",
15-
"lint:fix": "./node_modules/.bin/prettier --write 'src/**/*.{js,ts,css,html}' --write 'test/**/*.{js,ts,css,html}'",
16-
"lint:check": "./node_modules/.bin/eslint src test",
15+
"lint:fix": "prettier --write 'src/**/*.{js,ts,css,html}' --write 'test/**/*.{js,ts,css,html}'",
16+
"lint:check": "eslint src test",
1717
"lint": "npm run lint:fix --silent && npm run lint:check",
1818
"prepublishOnly": "npm ci && npm test",
1919
"postlint": "echo \"No issues.\"",

src/async-array.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ const { asyncFind } = require('./async-find'),
66
{ asyncMapSort } = require('./async-map-sort'),
77
{ asyncReduce } = require('./async-reduce'),
88
{ asyncSort } = require('./async-sort'),
9-
{ compareByUnicode } = require('./helpers');
9+
{ compareByUnicode } = require('./helpers'),
10+
{ noParam } = require('./constants');
1011

1112
/**
1213
* Async Array
@@ -68,11 +69,11 @@ class AsyncArray extends Array {
6869
return asyncMapSort(iterable, mappingCallback, comparisonCallback);
6970
}
7071

71-
asyncReduce(callback, accumulator = undefined) {
72+
asyncReduce(callback, accumulator = noParam) {
7273
return asyncReduce(this, callback, accumulator);
7374
}
7475

75-
static asyncReduce(iterable, callback, accumulator = undefined) {
76+
static asyncReduce(iterable, callback, accumulator = noParam) {
7677
return asyncReduce(iterable, callback, accumulator);
7778
}
7879

src/async-filter.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ async function asyncFilter(iterable, callback, thisArg = undefined) {
2020
iterable,
2121
await Promise.all(
2222
mapIterable(iterable, callback.bind(thisArg), {
23-
useEmptyElements: false,
24-
newlyAddedElements: false
23+
useEmptyElements: false
2524
})
2625
)
2726
);

src/async-find-index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ async function asyncFindIndex(iterable, callback, thisArg = undefined) {
1717
validateIsFunction(callback);
1818

1919
const tasks = mapIterable(iterable, callback.bind(thisArg), {
20-
useEmptyElements: true,
21-
newlyAddedElements: false
20+
useEmptyElements: true
2221
});
2322

2423
return Promise.race([

src/async-find.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ async function asyncFind(iterable, callback, thisArg = undefined) {
1717
validateIsFunction(callback);
1818

1919
const tasks = mapIterable(iterable, callback.bind(thisArg), {
20-
useEmptyElements: true,
21-
newlyAddedElements: false
20+
useEmptyElements: true
2221
});
2322

2423
return iterable[

src/async-for-each.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ async function asyncForEach(iterable, callback, thisArg = undefined) {
1717

1818
await Promise.all(
1919
mapIterable(iterable, callback.bind(thisArg), {
20-
useEmptyElements: false,
21-
newlyAddedElements: false
20+
useEmptyElements: false
2221
})
2322
);
2423
}

src/async-map.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ async function asyncMap(iterable, callback, thisArg = undefined) {
1818

1919
return Promise.all(
2020
mapIterable(iterable, callback.bind(thisArg), {
21-
useEmptyElements: false,
22-
newlyAddedElements: false
21+
useEmptyElements: false
2322
})
2423
);
2524
}

src/async-reduce.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
const {
2+
validateIsIterable,
3+
validateIsFunction,
4+
validateNonZeroLength
5+
} = require('./validation'),
6+
{ noParam } = require('./constants');
7+
18
/**
29
* Async Reduce
310
* ============
@@ -6,10 +13,35 @@
613
* @async
714
* @param {Object} iterable
815
* @param {Function} callback - callback(currentValue, index, array)
9-
* @param {any} [accumulator]
16+
* @param {any} [accumulator=noParam]
1017
* @return {any}
1118
* @throws {TypeError}
1219
*/
13-
async function asyncReduce() {}
20+
async function asyncReduce(iterable, transducer, accumulator = noParam) {
21+
validateIsIterable(iterable);
22+
validateIsFunction(transducer);
23+
const length = iterable.length;
24+
let i = 0;
25+
26+
if (accumulator === noParam) {
27+
try {
28+
validateNonZeroLength(iterable);
29+
} catch (e) {
30+
throw new TypeError(
31+
'asyncReduce of empty array with no accumulator given'
32+
);
33+
}
34+
35+
accumulator = iterable[0];
36+
i = 1;
37+
}
38+
39+
for (; i < length; i++) {
40+
// eslint-disable-next-line no-await-in-loop
41+
accumulator = await transducer(accumulator, iterable[i], i, iterable);
42+
}
43+
44+
return accumulator;
45+
}
1446

1547
module.exports = { asyncReduce };

src/constants.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* @const {Symbol} noParam
3+
* For representing when no parameter was passed to a function
4+
*/
5+
const noParam = Symbol('No argument passed for this parameter');
6+
7+
module.exports = { noParam };

src/helpers.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,18 @@
77
* @param {Function} callback
88
* @param {Object} [options]
99
* @param {Boolean} [options.useEmptyElements=true] - use empty elements of the array ?
10-
* @param {Boolean} [options.newlyAddedElements=false] - visit newly added elements ?
1110
* @return {Array}
1211
*/
13-
function mapIterable(
14-
iterable,
15-
callback,
16-
{ useEmptyElements = true, newlyAddedElements = false } = {}
17-
) {
18-
const tasks = [];
12+
function mapIterable(iterable, callback, { useEmptyElements = true } = {}) {
13+
const tasks = [],
14+
length = iterable.length;
1915

20-
for (let index = 0, length = iterable.length; index < length; index++) {
16+
for (let index = 0; index < length; index++) {
2117
if (!useEmptyElements && !(index in iterable)) {
2218
continue;
2319
}
2420

2521
tasks.push(callback(iterable[index], index, iterable));
26-
27-
if (newlyAddedElements) {
28-
length = iterable.length;
29-
}
3022
}
3123

3224
return tasks;

0 commit comments

Comments
 (0)