首页 > 解决方案 > 使用 MERN 堆栈从服务器到客户端获取数据的错误

问题描述

我正在构建一个 MERN Web 应用程序,并且我有一个错误,当我在客户端发出获取请求时,我没有从服务器获取正确的数据。

这是来自服务器的控制器函数,用于请求 GET http://localhost:5000/public_facility/:id

export const getPublicFacilityData = async (req, res) => {
    const { id } = req.params;

    if(!mongoose.Types.ObjectId.isValid(id)){
        return res.status(404).json({ message: `No valid public facility id: ${id}`});
    }

    try {
        const result = await PublicFacilityModel.findById(id, 'name data');
        res.status(200).json({result});
    } catch (error) {
        res.status(500).json({ message: 'Could not get public facility data'});
        console.log(error);
    }
}

这是我使用带有示例 ID 的邮递员或 VS REST 客户端扩展(与我在 MongoDB 中拥有的数据相同)得到的结果:

  "result": {
    "_id": "60269642b8f3741a7c6a54ei",
    "name": "TOWN HALL",
    "data": [
      {
        "year": 2019,
        "annual_data": [
          {
            "consumption": [10,10,10]
            "price": [],
            "concept": "Total"
          },
          {
            "consumption": [20,20,20],
            "price": [],
            "concept": "Electricity"
          }
        ]
      },
      {
        "year": 2018,
        "annual_data": [
          {
            "consumption": [30,30,30],
            "price": [],
            "concept": "Total"
          }
        ]
      }
    ]
  }
}

这是我从客户端用来发出请求的函数:

export const getPublicFacilityDatasets = async (id) => {
    if(id){
        try {           
            const res = await axios.get(`http://localhost:5000/public_facility/${id}`);
            
            //console.log('Result: ', res.data); 
            //console.log('Total consumption 2018', res.data.result.data[1].annual_data[0].consumption);
            ...

        } catch (error) {
            ...
        }
    }
}

这是我在客户端执行请求时收到的数据:

{
  "result": {
    "_id": "60269642b8f3741a7c6a54ei",
    "name": "TOWN HALL",
    "data": [
      {
        "year": 2019,
        "annual_data": [
          {
            "consumption": [10,10,10]
            "price": [],
            "concept": "Total"
          },
          {
            "consumption": [20,20,20],
            "price": [],
            "concept": "Electricity"
          }
        ]
      },
      {
        "year": 2018,
        "annual_data": [
          {
            "consumption": [10,10,10],
            "price": [],
            "concept": "Total"
          }
        ]
      }
    ]
  }
}

它看起来与我数据库中的数据相同,但 2018 年的总消费量 ( result.data[1].annual_data[0].consumption) 具有 2019 年的总消费量值。

我发现很奇怪,如果我console.log(res.data)在发出请求之前这样做,res.data.result.data[1].annual_data[0].consumption会有错误的值[10,10,10],但如果我这样做console.log(res.data.result.data[1].annual_data[0].consumption),它会显示正确的值[30,30,30]。看起来它们不是同一个对象,但我没有任何其他变量称为结果。

有没有人有任何想法?如果我需要提供更多详细信息,请告诉我。

标签: javascriptnode.jsjsonreactjsmern

解决方案


result.data - 数组。您正在按索引访问数组对象,但在数组中排序是可选的。有几种方法可以从前端的数组中获取数据:

  1. 按数组搜索并按唯一元素选择
const getDataByYear = (arr,year) =>{
return arr.find((x)=> x.year===year)
}
getDataByYear(res.data.result.data,2018)
  1. 对从服务器接收到的数据进行归一化处理,按标识符处理。这种情况下,需要将接收到的数据带入这种形式:array->Object
{
  "result": {
    "_id": "60269642b8f3741a7c6a54ei",
    "name": "TOWN HALL",
    "data": {
      "2019": {
        "year": 2019,
        "annual_data": [
          {
            "consumption": [10,10,10]
            "price": [],
            "concept": "Total"
          },
          {
            "consumption": [20,20,20],
            "price": [],
            "concept": "Electricity"
          }
        ]
      },
      "2018": {
        "year": 2018,
        "annual_data": [
          {
            "consumption": [10,10,10],
            "price": [],
            "concept": "Total"
          }
        ]
      }
    }
  }
}

您将访问诸如result.data[2018].annual_data[0].consumption

如果您没有通过单独的函数找到数组元素的索引并且不确定特定元素是否具有特定索引,则不要对数组使用索引访问。

有关数据规范化的更多信息:Redux 帖子

测试变体

我在我的 api 上测试了相同的方案,但我使用了一些其他代码。如果你愿意,你可以试试:

export const getPublicFacilityData = async (req, res) => {
    const { id } = req.params;

    if(!mongoose.Types.ObjectId.isValid(id)){
        return res.status(404).send({ message: `No valid public facility id: ${id}`});
    }

    try {
        const result = await PublicFacilityModel.findById(id, 'name data');
        res.status(200).send(result);
    } catch (error) {
        res.status(500).send({ message: 'Could not get public facility data'});
        console.log(error);
    }
}
export const getPublicFacilityDatasets = async (id) => {
    if(id){
        try {           
            const {data} = await axios.get(`http://localhost:5000/public_facility/${id}`);

console.log(data)
        } catch (error) {
            ...
        }
    }
}

推荐阅读