JSFiddle - React, Tailwind, and code Playground
by levchenko_d
JavaScript
/**
* Loop through array with a promise on done
* @param {array} array
* @param {function} iterateeFn - runs on each iteration, accepts `(array[index], index, next)`
* @returns {Promise}
*
* @example
* const myArr = [1,2,3];
*
* mapAsync(myArr, (item, index, next) => {
* console.log(item, index);
* next(null, index + 1);
* }).
* then((result) => {
* console.log('Done!', result);
* });
*/
const mapAsync = (array, iterateeFn) => {
let index = 0;
let result = [];
return new Promise((resolve, reject) => {
if(!Array.isArray(array)){
return reject('Expected first argument to be an array');
}
if(typeof iterateeFn !== 'function'){
return reject('Expected second argument to be a function');
}
/** Prevent infinite loop */
if(array.length === 0){
return resolve(result);
}
/**
* handle iteratee logic
*/
const handleItem = () => {
const item = array[index];
iterateeFn(item, index, (error, updatedItem) => {
if(error){
reject(error);
} else {
const isTheLastItem = index === array.length - 1;
result.push(updatedItem || item);
if(isTheLastItem) {
/** Exit cycle*/
resolve(result);
} else {
/** Run next cycle */
index++;
handleItem();
}
}
});
};
/** Run first cycle*/
handleItem();
});
};
/** General example */
const myArr = [1,2,3];
mapAsync(
myArr,
(item, index, next) => {
console.log(item, index);
next('This is custom error', index + 1);
}
).
then((result) => {
console.log('Done!', result);
})
.catch(error => console.error(error));
/** Second arg error...