This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 4 months ago.
Need to query downloading of file array
I have an array with URL's of files to dowload:
const arrUrl = [
'http://server.domain/path/file1.jpg',
'http://server.domain/path/file2.jpg',
'http://server.domain/path/file3.jpg',
];
when i try to download files with Axios and code:
arrUrl.forEach(async (element: string, i:number) => {
const response = await new Axios({responseType: 'stream'}).get(element);
await writeFile('./files/'+i, response.data);
console.log(element);
});
All files start downloading at one time. But how can i download files in query mode? one-by-one
This can be achieved using async function with for-in (index) of for-of (element) loop. Since we need to deal with loop index for-in is suitable here.
const arrUrl = [
'http://server.domain/path/file1.jpg',
'http://server.domain/path/file2.jpg',
'http://server.domain/path/file3.jpg',
];
async function downloadFiles(arrUrl) {
for (let index in arrUrl) {
const element = arrUrl[index];
const response = await new Axios({ responseType: 'stream' }).get(element);
await writeFile('./files/' + index, response.data);
}
}
downloadFiles(arrUrl);
Related
This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 7 months ago.
I have a situation where I need to read all the files in a directory and all its subdirectories. I wrote a basic function:
Although this is in React-Native, I'm not sure that matters (or maybe there is a react-native solution).
let fileList = [];
const readDir = async (dir) => {
// This line simply reads the contents of a directory, creating an array of strings
// of all the files and directories inside 'dir'.
const items = await FileSystem.readDirectoryAsync(dir);
items.forEach(async (item) => {
const f = await FileSystem.getInfoAsync(item); // Gets basic information about the item
if (f.isDirectory === true) {
readDir(f.uri); // f.uri is the location of the new directory to read
} else {
// runs if the item is a file
console.log("f.uri: ", f.uri);
fileList.push(f.uri); // A global variable
}
})
};
const parentDirectory = "parent_folder";
readDir(parentDirectory);
// Do more stuff here once all files have been read and added to 'fileList'
This seems to partially work as all the files in all the subdirectories are consoled out from inside the else {...} segment.
However, how can I know the loop is complete so I can continue the script and use 'fileList'?
Don't use forEach with async they don't work together and you can't await the loop. Use a standard for .. of loop, which works nicely with async/await
const readDir = async (dir) => {
const items = await FileSystem.readDirectoryAsync(dir);
for (let item of items) {
const f = await FileSystem.getInfoAsync(item);
if (f.isDirectory === true) {
await readDir(f.uri);
} else {
console.log("f.uri: ", f.uri);
fileList.push(f.uri);
}
}
}
And as readDir is async as well, you have of course either to await it also, or use then to continue once it is finished
async function foo() {
const parentDirectory = "parent_folder";
await readDir(parentDirectory);
//do some other stuff once readdir is finished.
}
or
const parentDirectory = "parent_folder";
readDir(parentDirectory).then(_ => {
//do some other stuff once readdir is finished.
}
This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 1 year ago.
I have an array of IDs, for each ID I want to make an axios.post call to create something in the database. I've done something like this.
const promises = ids.map(async (id) =>
await methodToCallAxiosPost(params, id)
);
await Promise.all(promises);
// do stuff
now I know that Promise.all runs when all of the promises are resolved which is useful to me to update the UI, but I also want to wait for each promise inside, something like this
const data1 = await methodToCallAxiosPost(params, id1)
const data2 = await methodToCallAxiosPost(params, id2)
const data3 = await methodToCallAxiosPost(params, id3)
Because I am getting potential lock conflicts in the database and I sometimes face issues.
I have tried using for await of but it seemed similar to Promise.all or I might be using it incorrectly.
You can't. They aren't promise aware methods. Use a regular for loop instead.
const results = [];
for (let i = 0; i < ids.length; i++) {
const result = await methodToCallAxiosPost(params, ids[i]);
results[i] = result;
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
async/await implicitly returns promise?
(5 answers)
Closed 2 years ago.
Get the value from a function in some other languages is simple like write return something
I can't get how to do it in JS from an async function.
const URL = `https://www.reddit.com/r/all.json`;
async function getPost() {
var list = [];
let response = await fetch(URL).then((res) => res.json());
let childList = await response.data.children;
childList.map((el) => {
let id = el.data.id;
let title = el.data.title;
list.push({
id: id,
title: title,
});
});
console.log(list);
}
var oo = getPost();
If you try the code like this everything work fine. But if to change console.log(list) inside getPOst() to return list and try to console.log(oo) nothing is showing
So... BIG thanks to #nick-parsons
that's the answer:
Oh, so a Promise is being shown. Your async function will wrap the >return value in a Promise, so that's expected. To "extract" the >value/list, you need to use .then(list => // use list here) on the >returned Promise. Or, if you're in a ES module, you can await the >Promise
This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 2 years ago.
The below JavaScript is returning a strange version of an array. The below forEach logs nothing to console. I'm probably missing something quite fundamental here, but I know for a fact that the array is populated...unless it's not populated until later due to being async and Chrome just evaluates the console.log after the fact?
let damageRollStringArr = []
monster.damage_types.forEach(async (damageTypeName) => {
const damageType = await checkResponseAndReturnValue(await DamageTypesService.findDamageType(damageTypeName.trim()))
if (damageType !== null) {
damageRollStringArr.push(damageType.damage)
}
})
damageRollStringArr.forEach(el => console.log(el))
// Was returning an empty array[] with objects inside?
return damageRollStringArr
Thanks
demageRollStringArr.forEach (2nd foreach) wont wait for monster.demage_types.forEach (1st foreach) to execute although there is async await in the first forEach
To achieve what you want to do, try this,
let damageRollStringArr = []
const promises = monster.damage_types.map(async (damageTypeName) => {
const damageType = await checkResponseAndReturnValue(await DamageTypesService.findDamageType(damageTypeName.trim()))
if (damageType !== null) {
damageRollStringArr.push(damageType.damage)
}
})
await Promise.all(promises)
damageRollStringArr.forEach(el => console.log(el))
return damageRollStringArr
Or, you can use normal for() loop to replace 1st foreach
let damageRollStringArr = []
for(let i = 0; i < monster.demage_types.length; i++) {
const damageType = await checkResponseAndReturnValue(await DamageTypesService.findDamageType(damageTypeName.trim()))
if (damageType !== null) {
damageRollStringArr.push(damageType.damage)
}
}
damageRollStringArr.forEach(el => console.log(el))
return damageRollStringArr
1st solution will run the loop parallel,
2nd solution will run the loop sequential
This question already has answers here:
How to return many Promises and wait for them all before doing other stuff
(6 answers)
Closed 2 years ago.
I am new to React JS. In my application I am facing a situation where I need to call an API multiple times with different url, like apiurl.com/abc, apiurl.com/xyz. These abc and xyz are stored in an array. Hence I wanted to use .map() to change the url to make multiple api calls. But in .map() async await wont work, so looking for some solutions if any. I have gone through few possible solution like with promises, but could not implement.
Here is my code:
export const someAction = () => async (dispatch, param) => {
let myArray = ["abc", "xyz"];
let id= "";
param1 = "someauthcode";
myArray.map((x) => {
id = x;
const myResponse = await loaders.myResponseApi(param1, id); *//This does not work as await should be in async call*
});
dispatch({ type: types.ARRAY_API, payload: myResponse });
}
So the idea is to make 2 api calls with apiurl.com/abc, apiurl.com/xyz. I have constructed the url (apiurl.com) in an different file.
Thanks in advance.
Turn your array into an array of promises and then use Promise.all
export const someAction = () => async(dispatch) => {
try {
const payload = await Promise.all(myArray.map(id => loaders.myResponseApi(param1,id)));
dispatch({type:types.ARRAY_API,payload});
} catch(err) {
// an error occurred in at least one of the promises
}
}
Instead of using .map() you can use a traditional for or while loop:
export const someAction = () => async (dispatch, param) => {
let myArray = ["abc", "xyz"];
let id= "";
param1 = "someauthcode";
let i = 0;
while (i < myArray.length) {
id = myArray[i];
const myResponse = await loaders.myResponseApi(param1, id);
// handle response here...
i++;
}
}