Created
January 25, 2016 05:06
-
-
Save jhurliman/82540feafc39ef03634c to your computer and use it in GitHub Desktop.
ES7 implementation of Array.map() and the equivalent for objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import PromisePool from 'es6-promise-pool' | |
/** | |
* Like Array.map() but supports promises and concurrency limiting. | |
* @param {array} array - Input array to map. | |
* @param {function} asyncFn(currentValue, index, array) - Called once for each | |
* value in the array. | |
* @param {number} [concurrencyLimit] - Optional cap on the number of | |
* asynchronous methods to execute at once. | |
* @returns {array} An array containing the mapped output values. | |
*/ | |
export async function mapAsync (array, asyncFn, concurrencyLimit) { | |
concurrencyLimit = concurrencyLimit || Number.MAX_SAFE_INTEGER | |
let outputError | |
const output = new Array(array.length) | |
function createAssigner (i) { return function (value) { output[i] = value } } | |
function setError (err) { outputError = (err instanceof Error) ? err : new Error(err) } | |
const generator = function *() { | |
for (let i = 0; i < array.length; i++) { | |
const promiseOrValue = asyncFn(array[i], i, array) | |
yield Promise.resolve(promiseOrValue).then(createAssigner(i), setError) | |
if (outputError) { return } | |
} | |
} | |
const pool = new PromisePool(generator(), concurrencyLimit) | |
await new Promise(resolve => pool.start().then(_ => resolve())) | |
if (outputError) throw outputError | |
return output | |
} | |
/** | |
* Like Array.map() but for objects and supporting promises and concurrency | |
* limiting. | |
* @param {object} obj - Input object to map. | |
* @param {function} asyncFn(currentValue, key, obj) - Called once for each | |
* property in the object. | |
* @param {number} [concurrencyLimit] - Optional cap on the number of | |
* asynchronous methods to execute at once. | |
* @returns {object} An object containing the mapped output properties. | |
*/ | |
export async function mapPropsAsync (obj, asyncFn, concurrencyLimit) { | |
concurrencyLimit = concurrencyLimit || Number.MAX_SAFE_INTEGER | |
const keys = Object.keys(obj) | |
const values = keys.map(key => obj[key]) | |
let outputError | |
const outValues = new Array(values.length) | |
function createAssigner (i) { return function (value) { outValues[i] = value } } | |
function setError (err) { outputError = (err instanceof Error) ? err : new Error(err) } | |
const generator = function *() { | |
for (let i = 0; i < values.length; i++) { | |
const promiseOrValue = asyncFn(values[i], keys[i], obj) | |
yield Promise.resolve(promiseOrValue).then(createAssigner(i), setError) | |
if (outputError) { return } | |
} | |
} | |
const pool = new PromisePool(generator(), concurrencyLimit) | |
await new Promise(resolve => pool.start().then(_ => resolve())) | |
if (outputError) throw outputError | |
const output = {} | |
keys.forEach((key, i) => output[key] = outValues[i]) | |
return output | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment