Pushing to an array in async function not working [duplicate]

百般思念 提交于 2020-04-11 16:27:27

问题


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.


回答1:


Two problems:

  1. You shouldn't be using .map for side effects. It returns a new array so you should make use of that.

  2. .map doesn't know anything about async 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 to await 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)
);



回答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.




回答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;
}


来源:https://stackoverflow.com/questions/54100855/pushing-to-an-array-in-async-function-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!