首页 > 解决方案 > 尝试使用 JavaScript 获取 CSV 数据时无休止的承诺循环

问题描述

我知道有很多关于如何使用 fetch 和从异步函数返回 Promise 的帖子。我读过你应该将依赖于获取的数据/内容的代码位移动到函数中,但我看不出我的设置是如何实现的。因此,在您将我的问题作为重复问题结束之前,我要求您完整阅读它并尝试记住当您刚接触编程并需要一些帮助时的感觉。

我正在构建一个 React 应用程序,我想在其中根据用户输入绘制一堆 CSV 数据。我正在尝试获取 CSV 数据,拉出我想要的两个变量,然后将其传递给 VictoryChart。这段代码成功获取数据,将其转换为由记录分隔的数组,然后创建一个新的对象数组(VictoryChart 需要的数据输入),其中只有两个字段我想成为我的变量:

  async function getData(filePath) {
    let dataArray = []
    await fetch(filePath)
      .then(response => {
        return response.text()
      })
      .then(data => CSVToArray(data))
      .then(data => {
        for (let i in data) {
          dataArray.push(
            { DateTime: data[i][0], OATemp: data[i][1]}
          )
        };
        return dataArray
      })
      .catch(error => alert(error))
  }

正如几个消息来源所建议的那样,我将尝试在返回 dataArray 之后将 VictoryChart 放入函数中,以将依赖于函数的所有内容保留在函数中,但我看不出如何控制页面的布局通过尝试调用然后生成图形的函数。我不明白你是如何用它构建 DOM 的(我什至使用它对吗?)。我是 React 的新手(通常是一个没有经验的程序员),所以这可能是问题的一部分。

对我来说唯一有意义的是异步函数返回数据,以便我可以将其传递到 VictoryChart。但是似乎不可能从它被包装的承诺中提取从函数返回的任何东西。我被告知要使用.then,但这最终只会返回一个承诺。看起来很乱伦......具体来说,我最近的尝试看起来像这样(只是使用警报来“看到”正在发生的事情):

  alert(getData('./2021WeatherData.csv').then(data => {return data}))

希望我只是不明白如何.then按照其他人的建议正确使用。我花了很多很多时间尝试了几十种不同的版本,并在谷歌上搜索了我能想到的问题的每一个同义词。我知道我错过了一些东西,所以我很感激任何帮助。

***提供附加代码 下面是我理解的 React 应用程序的 DOM(请纠正我的措辞等错误)。这会将我的应用程序呈现给浏览器。

return (
  <div className="App">
    <header className="App-header">
      <div className='Header-button-container'>
        <button onClick={() => alert('Weather')}>
          Weather
        </button>
        <button onClick={() => alert('1st Floor')}>
          1st Floor
        </button>
        <button onClick={() => alert('2nd Floor')}>
          2nd Floor
        </button>
      </div>
    </header>
    <VictoryChart>
      <VictoryLine data={getData('./2021WeatherData.csv').then(data => { return data })} x='DateTime' y='OATemp' />
    </VictoryChart>
  </div>
);

对我来说,这决定了页面上的显示方式。我注意到这里的所有东西都是一个标签,所以我不明白如何在 VictoryLine 标签存在的地方插入一个函数。VictoryLine 图的“数据”属性需要数据作为对象数组,这就是我试图从我的 getData 函数输出的内容(但它一直被包装在一个该死的承诺中!!)。我可以使用我在应用程序中声明的虚拟数据集使其正常工作,但是在尝试获取数据时我被卡住了。而且由于我无法从函数中“取出”数据(似乎所有可能的事情都是在函数内部做事),我只是陷入困境和困惑。这里的目的是能够单击一个按钮并获取相关数据以绘制图表。

标签: javascriptreactjspromisefetch-api

解决方案


听起来您只是无法将 CSV 结果传递给您的绘图功能。getData首先,您需要从;返回您的值。目前它没有返回任何东西:

async function getData(filePath) {
  let dataArray = []
  return fetch(filePath)
  ...
}

然后您可以通过以下两种方式之一传递您的结果:

function theGraphFunction(data) {
  // this graphs your data
}

getData("./path/to/data.csv").then(data => theGraphFunction(data));

或者

(async () => {
  const data = await getData("./path/to/data.csv");
  theGraphFunction(data);
})()

现在您已经更新了问题以包含有关您实际尝试做的事情的信息,您可以执行以下操作:

import {useEffect, useState} from "react";

function App() {
  const [graphData, setGraphData] = useState(null);

  useEffect(() => {
    getData("./path/to/data.csv").then(data => setGraphData(data));
  }, [])

  // only include this if you don't want to render the component
  // until data is loaded
  if(!graphData) {
    return null;
  }

  return (
    <div className="App">
      <header className="App-header">
        <div className='Header-button-container'>
          <button onClick={() => alert('Weather')}>
            Weather
          </button>
          <button onClick={() => alert('1st Floor')}>
            1st Floor
          </button>
          <button onClick={() => alert('2nd Floor')}>
            2nd Floor
          </button>
        </div>
      </header>
      <VictoryChart>
        <VictoryLine data={graphData} x='DateTime' y='OATemp' />
      </VictoryChart>
    </div>
  );
}

推荐阅读