Как бы я использовал Promises для решения этой проблемы синхронизации в React? - PullRequest
0 голосов
/ 02 апреля 2020

Я работаю над групповым проектом, в котором нам нужно сделать приложение для погоды. Я делаю раздел подробностей, который отображает такие значения, как температура, влажность, вероятность дождя и т. Д. c. из API. В этом проекте я использую два разных API, так как в OpenWeatherMap нет нужных мне данных. Другой раздел нашего приложения получает местоположение и передается в мой раздел, где он без проблем помещается в URL-адрес OpenWeatherMap.

constructor(props){
    super(props);
}

componentDidMount() {
    if(this.props.location) {
        this.fetchWeatherData1();
        this.fetchWeatherData2();
    }
}

componentDidUpdate(prevProps) {
    if(this.props.location != prevProps.location) {
        this.fetchWeatherData1();
        this.fetchWeatherData2();
    }
}

fetchWeatherData1 = () => {
    let urlOWM = "http://api.openweathermap.org/data/2.5/weather?q=" + this.props.location + "&units=metric&APPID=" + API_KEY_OWM;
    $.ajax({
        url: urlOWM,
        dataType: "jsonp",
        success : this.parseFirstResponse,
        error : function(req, err){ console.log('API call failed ' + err); }
    })
}

parseFirstResponse = (parsed_json) => {
    var feelsLike = this.formatTemp(parsed_json['main']['feels_like']);
    var humidity = this.formatPercentage(parsed_json['main']['humidity']);
    var wind = this.formatSpeed(parsed_json['wind']['speed']);
    var visib = this.formatVis(parsed_json['visibility']);
    var cloud = this.formatPercentage(parsed_json['clouds']['all']);
    var lat = this.formatString(parsed_json['coord']['lat']);
    var long = this.formatString(parsed_json['coord']['lon']);

    // set states for fields so they could be rendered later on
    this.setState({
        feelsLike: feelsLike,
        humidity: humidity,
        windSpeed: wind,
        visibility: visib,
        cloudCover: cloud,
        latitude: lat,
        longitude: long
    });      
}

В parseFirstResponse () я сохраняю значения широты и долготы для местоположения. Я должен сделать это, потому что второй URL API (DarkSky) может принимать координаты только по какой-то причине. Вот код ниже, где я помещаю значения состояния для широты и долготы в URL:

fetchWeatherData2 = () => {
    let urlDS = "https://api.darksky.net/forecast/" + API_KEY_DS + "/" + this.state.latitude + "," + this.state.longitude + "?exclude=minutely,hourly,daily,alerts,flags";
    $.ajax({
        url: urlDS,
        dataType: "jsonp",
        success : this.parseSecondResponse,
        error : function(req, err){ console.log('API call failed ' + err); }
    }) 
}

parseSecondResponse = (parsed_json) => {
    var precipChance = parsed_json['currently']['precipProbability'];
    var precipType = "";

    if (precipChance == 0.0) {
        precipType = "Precipitation";
    }
    else {
        precipType = this.capitalize(parsed_json['currently']['precipType']);
    }

    precipChance = this.formatDecimaltoPercentage(precipChance);
    var uv = parsed_json['currently']['uvIndex'];
    var dew = this.formatTemp(this.fToC(parsed_json['currently']['dewPoint']));

    // set states for fields so they could be rendered later on
    this.setState({
        precipChance: precipChance,
        precipType: precipType,
        uvIndex: uv,
        dewPoint: dew
    });      
}

Когда я запускаю этот код и помещаю местоположение в первый раз, я получаю ошибку в консоль с надписью «Не удалось загрузить ресурс: сервер ответил с состоянием 400 ()», а URL-адрес выглядит следующим образом: https://api.darksky.net/forecast/767ed401d519be925156b6c885fce737/undefined, неопределенный? exclude = поминутно, ежечасно, ежедневно, оповещения, флаги и обратный вызов = jQuery34106961395668750288_1585829837010 & _ = 1585829837011 Когда я помещаю второе, другое местоположение, но без обновления страницы, URL и вызов API работают без проблем.

Координаты местоположения должны быть там, где находятся слова "undefined, undefined". Я попытался console.log () значения широты и долготы в моей функции parseSecondResponse и получил правильные значения. Я думаю, что это проблема синхронизации, но я не слишком уверен.

Помещение функций fetchWeatherData () в явный порядок 1, а затем 2 в моей функции componentDidMount (), похоже, не помогает. Я читал об использовании Promises, но я не очень знаком с React, поэтому не уверен, как их реализовать / если они решат эту проблему.

1 Ответ

0 голосов
/ 02 апреля 2020

Я внес небольшие изменения:

  1. использовать fetch ;
  2. удалить fetchWeatherData2 из componentDidMount;
  3. использовать componentDidUpdate;
import React from 'react';

class Component extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      latitude: null,
      longitude: null,
    };
  }

  componentDidMount() {
    const { location } = this.props;

    if (location) {
      this.fetchWeatherData1(location);
      //fetchWeatherData2() your cannot call this because latitude and longitude === null
    }
  }

  componentDidUpdate(prevProps, prevState) {
    const { location: prevLocation } = prevState;
    const { location: currLocation } = this.props;
    const {
      latitude: prevLatitude,
      longitude: prevLongitude,
    } = prevState;
    const {
      latitude: currLatitude,
      longitude: currLongitude,
    } = this.state;

    if (prevLocation !== currLocation) {
      this.fetchWeatherData1(currLocation);
    }

    if (prevLatitude !== currLatitude || prevLongitude !== currLongitude) {
      this.fetchWeatherData2(currLatitude, currLongitude);
    }
  }

  fetchWeatherData1(location) {
    fetch(http://api.openweathermap.org/data/2.5/weather?q=${location}&units=metric&APPID=${API_KEY_OWM}`)
      .then(res => res.json())
      .then((data) => {
        // parse you data here
        this.setState(prevState => ({
          latitude: data.coord.lat,
          longitude: data.coord.long,
        }));
      })
      .catch(({ message }) => {
        console.error(`API call failed: ${message}`);
      });
  }

  fetchWeatherData2(latitude, longitude) {
    fetch(https://api.darksky.net/forecast/${API_KEY_DS}/${latitude},${longitude}?exclude=minutely,hourly,daily,alerts,flags`)
      .then(res => res.json())
      .then((data) => {
        // parse you data here
      })
      .catch(({ message }) => {
        console.error(`API call failed: ${message}`);
      });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...