2从请求获取数据之前axios请求问题呈现

时间:2020-03-22 18:54:51

标签: reactjs asynchronous async-await get axios

我正在构建一个类似于React.js中AccuWeather的天气应用程序。

axios.get请求有问题。我需要从2个网址获取数据。第二个请求(预测)更大。因此,当我想在应用程序的某些部分中获得城市天气预报时,在我从Axios请求中获取数据之前先渲染DOM。

我试图在代码中使用异步并等待,但是没有成功。您可以在下面找到 getCityWeather 函数,其中包含这2个Axios请求。有想法吗?

getCityWeather = event => {
  axios
    .get(
      "https://api.openweathermap.org/data/2.5/weather?q=" +
        this.state.city +
        "&units=metric&appid=" +
        this.state.appiID
    )
    .then(weather => {
      console.log(weather);
      this.setState({
        currentCityWeather: weather.data.weather,
        currentCityName: weather.data.name,
        currentCityCountry: weather.data.sys.country,
        CityWeatherMain: weather.data.main,
        CityWeatherWind: weather.data.wind,
        CityWeatherClound: weather.data.clouds,
        cityLoaded: true
      });
    })
    .catch(error => {
      console.log(error);
    });

  axios
    .get(
      "https://api.openweathermap.org/data/2.5/forecast?q=" +
        this.state.city +
        "&units=metric&appid=" +
        this.state.appiID
    )
    .then(forecast => {
      console.log(forecast);
      this.setState({
        CityForecastDataList: forecast.data.list,
        cityLoaded: true
      });
    })
    .catch(error => {
      console.log(error);
    });
  event.preventDefault();
};

2 个答案:

答案 0 :(得分:0)

尝试下面的代码。

const baseUrl = 'https://api.openweathermap.org/data/2.5';

const getCityWeather = (event) => {
  event.preventDefault();
  const { city, appiID } = this.state;
  const urls = [
    `${baseUrl}/weather?q=${city}&units=metric&appid=${appiID}`,
    `${baseUrl}/forecast?q=${city}&units=metric&appid=${appiID}`,
  ];
  const promises = urls.map(s => axios.get(s));
  
  Promise.all(promises)
    .then(([weatherResponse, forecastResponse]) => {
      const {
        date: {
          weather,
          name,
          sys: { country },
          main,
          wind,
          clouds,
        },
      } = weatherResponse;
      const {
        data: { list },
      } = forecastResponse;

      this.setState({
        currentCityWeather: weather,
        currentCityName: name,
        currentCityCountry: country,
        CityWeatherMain: main,
        CityWeatherWind: wind,
        CityWeatherClound: clouds,
        CityForecastDataList: list,
        cityLoaded: true,
      });
    })
    .catch(({ message }) => {
      console.error(message);
    });
};

答案 1 :(得分:0)

感谢基里尔的答案,

我尝试实现您的代码,但得到

ReferenceError: Cannot access 'promises' before initialization
getCityWeather
src/containers/WeatherData/WeatherData.js:39
  36 |   `${baseUrl}/weather?q=${city}&units=metric&appid=${appiID}`,
  37 |   `${baseUrl}/forecast?q=${city}&units=metric&appid=${appiID}`
  38 | ];
> 39 | const promises = urls.map(s => axios.get(s),
     | ^  40 | 
  41 | Promise.all(promises)
  42 |   .then(([weatherResponse, forecastResponse]) => {

请在下面找到我使用的基于类的组件的实现


getCityWeather = (event) => {
    event.preventDefault();
    const baseUrl = 'https://api.openweathermap.org/data/2.5';

    const { city, appiID } = this.state;
    const urls = [
      `${baseUrl}/weather?q=${city}&units=metric&appid=${appiID}`,
      `${baseUrl}/forecast?q=${city}&units=metric&appid=${appiID}`
    ];
    const promises = urls.map(s => axios.get(s));

    Promise.all(promises)
      .then(([weatherResponse, forecastResponse]) => {
        const {
          date: {
            weather,
            name,
            sys: { country },
            main,
            wind,
            clouds
          },
        } = weatherResponse;
        const {
          data: { list },
        } = forecastResponse;

        this.setState({
          currentCityWeather: weather,
          currentCityName: name,
          currentCityCountry: country,
          CityWeatherMain: main,
          CityWeatherWind: wind,
          CityWeatherClound: clouds,
          CityForecastDataList: list,
          cityLoaded: true,
        });
      })
      .catch(({ message }) => {
        console.error(message);
      })
    )}