-
-
Save atinux/fd2bcce63e44a7d3addddc166ce93fb2 to your computer and use it in GitHub Desktop.
const waitFor = (ms) => new Promise(r => setTimeout(r, ms)) | |
const asyncForEach = async (array, callback) => { | |
for (let index = 0; index < array.length; index++) { | |
await callback(array[index], index, array) | |
} | |
} | |
const start = async () => { | |
await asyncForEach([1, 2, 3], async (num) => { | |
await waitFor(50) | |
console.log(num) | |
}) | |
console.log('Done') | |
} | |
start() |
I do believe the original forEach from ES6 should understand the async/await call and wait for the inner called code to resolve, and then iterate with a new value.
Hello is there a way that it can be apply using an axios? cos base on what i understand the waitFor is set statically, so how will it wait for a axios response
Thanks for the snippet and article!
TypeScript version for anyone interested:
export async function asyncForEach<T>(array: T[], callback: (item: T, index: number, allItems: T[]) => void) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
Thanks so much for this snippet and explanation! Implemented in this webpack plugin I wrote that creates a json file from a data endpoint. I wanted to use an array and this was perfect!
The given sample waits for each await to finish before processing the next item in the array. I actually wanted to process my items in parallel but wait for all of them to be done. I wanted to bake 6 cakes, but if each cake takes 10 minutes, I wanted to bake 6 cakes at once and be done in ~10 minutes, instead of 60.
I ended up doing something like this:
export async function asyncForEach<T>(array: T[], callback: (item: T, index: number, allItems: T[]) => void) {
await Promise.all(array.map(callback));
}
This stack overflow post was helpful in understanding what I wanted: https://stackoverflow.com/a/37576787
Thank you very much for this snippet, I passed in parameter of your function asyncForEach, the Object.keys() param, it works wonderfully !
const request = async () => {
await asyncForEach(Object.keys(category), async (item) => {
await waitFor(50)
console.log(item)
console.log(category[item])
})
console.log('Done')
};
const { data } = await request();
This is so simple yet so brilliant. Kudos
Object.defineProperty(Object.prototype, 'eachObjectKey', {writable: true, value:
async function (p, f, next) {
var promises = [];
for (var key in this) {
if (p=='await') {
//(in order)
promises.push(await new Promise( (resolve, reject) => f(key, this[key], resolve)));
} else {
//(in parallel)
promises.push(new Promise( (resolve, reject) => f(key, this[key], resolve)));
}
}
await Promise.all(promises).then(next);
}
});
var obj = [1, 2, 3, 4];
var f = function(key, value, next) {
setTimeout(function() {
console.log(key, value);
if (value==2) return next('error');
next('OK');
}, value*100);
}
console.time('app');
console.log('\nstart in order');
obj.eachObjectKey('await', f, function(results) {
console.log('Done!');
console.log(results);
console.timeEnd('app');
console.time('app');
console.log('\nstart in parallel');
obj.eachObjectKey('not await', f, function(results) {
console.log('Done!');
console.log(results);
console.timeEnd('app')
});
});
I don´t get why callback reicive 3 arguments, in the start function the call of asyncForEach method the second parameter is callback and is just sending one argument ... can some explain step by step?
Here's my typescript version (Basically @wodCZ's codeblock) with the ability to return data which is readable in the form of an array
async function asyncForEach<T = any>(array: T[], callback: (value: T, index?: number, array?: T[]) => any): Promise<any[]> {
const data: any[] = [];
for (let index = 0; index < array.length; index++) {
await (async () => {
const item = await callback(array[index], index, array);
if (item !== undefined) data.push(item);
return;
})();
}
return Promise.resolve(data);
}
I feel like this is just a glorified promise.all at this point.
Why not use for await()
?
const waitFor = (ms) => new Promise(r => setTimeout(r, ms))
const start = async () => {
for await (num of [1, 2, 3]) {
await waitFor(50)
console.log(num)
};
console.log('Done')
}
start()
Thanks for this piece of code, works like a charm...
would it be bad design / coding do define a prototype function for array like this:
Array.prototype.forEachAsync = async function(callback){ // this represents our array for (let index = 0; index < this.length; index++) { // We call AND AWAIT the callback for each entry await callback(this[index], index, this); } };
to later have calls like this:
await allFiles.forEachAsync(async (aFile) => { //DO AND WAIT FOR ASYNC STUFF BEFORE CARRYING ON TO NEXT aFile }