mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 16:29:34 +00:00
feat(core-utils): add mapAsync and reduceAsync utils
This commit is contained in:
parent
ea3f7fa37e
commit
0168a2758a
70
packages/core/utils/lib/__tests__/async.test.js
Normal file
70
packages/core/utils/lib/__tests__/async.test.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { mapAsync, reduceAsync } = require('../async');
|
||||||
|
|
||||||
|
describe('Async utils', () => {
|
||||||
|
describe('mapAsync', () => {
|
||||||
|
test('Should return a simple array of numbers', async () => {
|
||||||
|
const numberPromiseArray = [Promise.resolve(1), Promise.resolve(2)];
|
||||||
|
|
||||||
|
const mapFunc = mapAsync(numberPromiseArray);
|
||||||
|
const result = await mapFunc((number) => number + 1);
|
||||||
|
|
||||||
|
expect(result).toEqual([2, 3]);
|
||||||
|
});
|
||||||
|
test('Should work with mix of promises and values', async () => {
|
||||||
|
const numberMixArray = [1, Promise.resolve(2)];
|
||||||
|
|
||||||
|
const mapFunc = mapAsync(numberMixArray);
|
||||||
|
const result = await mapFunc((number) => number + 1);
|
||||||
|
|
||||||
|
expect(result).toEqual([2, 3]);
|
||||||
|
});
|
||||||
|
test('Should throw an error', async () => {
|
||||||
|
const numberPromiseArray = [Promise.resolve(1), Promise.resolve(2)];
|
||||||
|
|
||||||
|
const mapFunc = mapAsync(numberPromiseArray);
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
await mapFunc(() => {
|
||||||
|
throw new Error('test');
|
||||||
|
});
|
||||||
|
}).rejects.toThrow('test');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('reduceAsync', () => {
|
||||||
|
test('Should return a incremented number', async () => {
|
||||||
|
const numberPromiseArray = [Promise.resolve(1), Promise.resolve(2)];
|
||||||
|
|
||||||
|
const reduceFunc = reduceAsync(numberPromiseArray);
|
||||||
|
const result = await reduceFunc(
|
||||||
|
(previousValue, currentValue) => previousValue + currentValue,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual(13);
|
||||||
|
});
|
||||||
|
test('Should work with mix of promises and values', async () => {
|
||||||
|
const numberMixArray = [1, Promise.resolve(2)];
|
||||||
|
|
||||||
|
const reduceFunc = reduceAsync(numberMixArray);
|
||||||
|
const result = await reduceFunc(
|
||||||
|
(previousValue, currentValue) => previousValue + currentValue,
|
||||||
|
10
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual(13);
|
||||||
|
});
|
||||||
|
test('Should throw an error', async () => {
|
||||||
|
const numberPromiseArray = [Promise.resolve(1), Promise.resolve(2)];
|
||||||
|
|
||||||
|
const reduceFunc = reduceAsync(numberPromiseArray);
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
await reduceFunc(() => {
|
||||||
|
throw new Error('test');
|
||||||
|
});
|
||||||
|
}).rejects.toThrow('test');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
69
packages/core/utils/lib/async.js
Normal file
69
packages/core/utils/lib/async.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
function pipeAsync(...methods) {
|
||||||
|
return async (data) => {
|
||||||
|
let res = data;
|
||||||
|
|
||||||
|
for (const method of methods) {
|
||||||
|
res = await method(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map function callback.
|
||||||
|
* @callback mapAsyncCallback
|
||||||
|
* @param {*} value
|
||||||
|
* @param {number} index
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Async iteration over an array of promises
|
||||||
|
* @param {promise<*>[]} promiseArray
|
||||||
|
* @returns {function(callback: mapAsyncCallback): promise<*[]>}
|
||||||
|
*/
|
||||||
|
function mapAsync(promiseArray) {
|
||||||
|
/**
|
||||||
|
* @param {mapAsyncCallback} callback
|
||||||
|
* @returns promise<*[]>
|
||||||
|
*/
|
||||||
|
return (callback) => {
|
||||||
|
const transformedPromiseArray = promiseArray.map(async (promiseValue, index) => {
|
||||||
|
const value = await promiseValue;
|
||||||
|
return callback(value, index);
|
||||||
|
});
|
||||||
|
return Promise.all(transformedPromiseArray);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce function callback.
|
||||||
|
* @callback reduceAsyncCallback
|
||||||
|
* @param {*} previousValue
|
||||||
|
* @param {*} currentValue
|
||||||
|
* @param {number} index
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Async chain over an array of promises
|
||||||
|
* @param {promise<*>[]} promiseArray
|
||||||
|
* @returns {function(callback: reduceAsyncCallback, initialValue?: *): promise<*>}
|
||||||
|
*/
|
||||||
|
function reduceAsync(promiseArray) {
|
||||||
|
/**
|
||||||
|
* @param {reduceAsyncCallback} callback
|
||||||
|
* @param {*} [initialValue]
|
||||||
|
* @returns promise<*>
|
||||||
|
*/
|
||||||
|
return (callback, initialValue) =>
|
||||||
|
promiseArray.reduce(async (previousPromise, currentValue, index) => {
|
||||||
|
const previousValue = await previousPromise;
|
||||||
|
return callback(previousValue, await currentValue, index);
|
||||||
|
}, Promise.resolve(initialValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mapAsync,
|
||||||
|
reduceAsync,
|
||||||
|
pipeAsync,
|
||||||
|
};
|
@ -37,7 +37,7 @@ const providerFactory = require('./provider-factory');
|
|||||||
const pagination = require('./pagination');
|
const pagination = require('./pagination');
|
||||||
const sanitize = require('./sanitize');
|
const sanitize = require('./sanitize');
|
||||||
const traverseEntity = require('./traverse-entity');
|
const traverseEntity = require('./traverse-entity');
|
||||||
const pipeAsync = require('./pipe-async');
|
const { pipeAsync } = require('./async');
|
||||||
const convertQueryParams = require('./convert-query-params');
|
const convertQueryParams = require('./convert-query-params');
|
||||||
const importDefault = require('./import-default');
|
const importDefault = require('./import-default');
|
||||||
const template = require('./template');
|
const template = require('./template');
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports =
|
|
||||||
(...methods) =>
|
|
||||||
async (data) => {
|
|
||||||
let res = data;
|
|
||||||
|
|
||||||
for (const method of methods) {
|
|
||||||
res = await method(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
|
@ -4,7 +4,7 @@ const { isArray } = require('lodash/fp');
|
|||||||
|
|
||||||
const traverseEntity = require('../traverse-entity');
|
const traverseEntity = require('../traverse-entity');
|
||||||
const { getNonWritableAttributes } = require('../content-types');
|
const { getNonWritableAttributes } = require('../content-types');
|
||||||
const pipeAsync = require('../pipe-async');
|
const { pipeAsync } = require('../async');
|
||||||
|
|
||||||
const visitors = require('./visitors');
|
const visitors = require('./visitors');
|
||||||
const sanitizers = require('./sanitizers');
|
const sanitizers = require('./sanitizers');
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
const { curry } = require('lodash/fp');
|
const { curry } = require('lodash/fp');
|
||||||
|
|
||||||
const pipeAsync = require('../pipe-async');
|
const { pipeAsync } = require('../async');
|
||||||
const traverseEntity = require('../traverse-entity');
|
const traverseEntity = require('../traverse-entity');
|
||||||
|
|
||||||
const { removePassword, removePrivate } = require('./visitors');
|
const { removePassword, removePrivate } = require('./visitors');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user