【问题标题】:Pushing to an array in async function not working [duplicate]在异步函数中推送到数组不起作用[重复]
【发布时间】:2019-06-03 16:19:28
【问题描述】:

这是我的代码:

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);
    }
}

让我感到困惑的是,异步函数“getPhotoData”中的“console.log(body)”完美地返回了 JSON 对象。

但是异步函数“getPhotoData”之外的数组仍然返回为空,“[]”。

我不确定对象是否没有被成功推送,或者这是否是 async/await 的某种问题。我来自回调,所以这对我来说仍然是新的。

我在 Ubuntu 18.10 上使用 Node.js v8.12.0。

【问题讨论】:

    标签: javascript node.js asynchronous async-await


    【解决方案1】:

    由于回调是异步的,您需要等待所有映射函数完成后才能打印新的propertyPhotoList - 这可以通过Promise.all 完成。如果您只是 return 新数组中所需的项目,则无需分配给外部数组:

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

    【讨论】:

      【解决方案2】:

      两个问题:

      1. 您不应该使用 .map 来获得副作用。它返回一个新数组,因此您应该使用它。

      2. .mapasync 函数一无所知。您所做的只是创建一系列承诺。当.map 并且您的函数返回时,承诺还没有“完成”。你需要await所有这些。

      话虽如此:

      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)
      );
      

      【讨论】:

        【解决方案3】:

        你需要使用Promise.allawait

        await Promise.all(propertyData.PropertyPhotos.map(getPhotoData));
        

        这是完整的修复代码:

        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);
            }
        }
        

        您的代码无法正常工作的原因是您没有等待对getPhotoData 的所有调用完成后再发送响应。

        【讨论】:

        • 是的,有效。非常感谢!
        • 这帮助我在尝试了大约 12 小时后修复了自己的代码。非常感谢!
        猜你喜欢
        • 1970-01-01
        • 2021-10-02
        • 2019-07-27
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 2020-12-19
        • 1970-01-01
        • 2023-01-29
        相关资源
        最近更新 更多