Pushing to an array in async function not working
Solution 1
Two problems:
You shouldn't be using
.map
for side effects. It returns a new array so you should make use of that..map
doesn't know anything aboutasync
functions. All you are doing is creating an array of promises. When.map
and your function returns, the promises are not "done" yet. You need toawait
all of them.
With that said:
async function getPhotoData(item, index){
const id = item.split('#')[1];
const response = await fetch(`http://localhost:4000/api/propertyphoto/${id}`);
return await response.json();
}
const propertyPhotoList = await Promise.all(
propertyData.PropertyPhotos.map(getPhotoData)
);
Solution 2
You need to use Promise.all
and await
:
await Promise.all(propertyData.PropertyPhotos.map(getPhotoData));
Here's the complete code with the fix:
exports.propertyById = async (req, res) => {
try {
const {propertyId} = _.get(req, 'params'),
propertyData = await bService.getPropertyById(propertyId);
console.log(propertyData);
const propertyPhotoList = [];
async function getPhotoData(item, index){
const id = item.split('#')[1];
const response = await fetch(`http://localhost:4000/api/propertyphoto/${id}`);
const body = await response.json();
console.log(body);
propertyPhotoList.push(body);
}
await Promise.all(propertyData.PropertyPhotos.map(getPhotoData));
console.log(propertyPhotoList);
return res.success(res, propertyData);
} catch (err) {
return res.error(res, err.response.status || 500, err.response.statusText || err);
}
}
The reason your code isn't working is because you're not waiting for all the calls to getPhotoData
to finish before sending the response.
Solution 3
Because the callback is asynchronous, you need to wait for all of the mapping functions to complete before printing the new propertyPhotoList
- this can be done with Promise.all
. There's no need to assign to an external array, either if you just return
the item you want in the new array:
const propertyPhotoList = await Promise.all(
propertyData.PropertyPhotos.map(getPhotoData)
);
async function getPhotoData(item, index){
const id = item.split('#')[1];
const response = await fetch(`http://localhost:4000/api/propertyphoto/${id}`);
const body = await response.json();
return body;
}
Admin
Updated on July 09, 2022Comments
-
Admin almost 2 years
Here is my code:
exports.propertyById = async (req, res) => { try { const {propertyId} = _.get(req, 'params'), propertyData = await bService.getPropertyById(propertyId); console.log(propertyData); const propertyPhotoList = []; async function getPhotoData(item, index){ const id = item.split('#')[1]; const response = await fetch(`http://localhost:4000/api/propertyphoto/${id}`); const body = await response.json(); console.log(body); propertyPhotoList.push(body); } propertyData.PropertyPhotos.map(getPhotoData); console.log(propertyPhotoList); return res.success(res, propertyData); } catch (err) { return res.error(res, err.response.status || 500, err.response.statusText || err); } }
What's confusing me it that the 'console.log(body)' inside the asynchronous function 'getPhotoData' is returning the JSON object perfectly fine.
But the array outside of the asynchronous function 'getPhotoData' is still returning as empty, '[]'.
I am unsure whether the object is not being successfully being pushed, or if this is some sort of issue with async/await. I am coming from callbacks so this is still new to me.
I am using Node.js v8.12.0 on Ubuntu 18.10.
-
Admin over 5 yearsYup that worked. Thanks so much!
-
Chrissy LeMaire almost 3 yearsThis helped me fix my own code after about 12 hours of trying. Thank you so much!