Как использовать fetch () для заполнения переменной данными с сервера? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть функция, которая получает данные из API Open Weather и присваивает некоторые значения свойствам innerText некоторых HTML элементов. Эта часть работает нормально.

Но мне также нужно сохранить одно из этих значений (data["main"]["temp"]) в свойстве объекта (userData.temp).

//Function to get data from Open Weather
const getWeatherData = () => {
  let zipInputValue = document.getElementById("zip").value;
  const weatherUrl = `http://api.openweathermap.org/data/2.5/weather?zip=${zipInputValue},${weatherCountryCode}&units=metric&appid=`;
  fetch(weatherUrl + weatherApiKey).then((res) => {
    if (res.status != 200) {
      console.log("Looks like there's been a problem.");
      return;
    }
    res.json().then((data) => {
      descriptionElement.innerText = "Weather: " + data["weather"][0]["description"];
      currenttempElement.innerText = "Temperature:" + data["main"]["temp"] + " °C";
      userData.temp = data["main"]["temp"];
      mintempElement.innerText = "Min.:" + data["main"]["temp_min"] + " °C";
      maxtempElement.innerText = "Max.:" + data["main"]["temp_max"] + " °C";
    });
  });  
  console.log(userData.temp);
};

В конце В моем коде есть функция generate(), запускаемая событием щелчка, которая вызывает getWeatherData(), а затем отправляет userData.temp на сервер, вызывая функцию postProjectData(userData).

/*---------- Post Data to the Server ---------- */

const postProjectData = async (userData) => {
  const rawResponse = await fetch("http://localhost:8080/addData", {
    method: "POST",
    body: JSON.stringify(userData),
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
  });
  const response = await rawResponse.json();
  return response;
};

/*---------- Generate Entry ---------- */

const btn = document.getElementById("generate");
btn.addEventListener("click", generate);

function generate() {
  getWeatherData();
  console.log("test");

  userData.date = newDate;
  userData.userResponse = getUserResponse();

  postProjectData(userData);

  getProjectData();
}

Однако Когда это событие щелчка вызывается впервые, свойство становится пустым для сервера. Во второй раз это соответствует значению предыдущей итерации. Это означает, что это также одна итерация позади.

Я предполагаю, что это потому, что когда браузер получает fetch внутри getWeatherData(), поскольку это асинхронная функция, он переходит к postProjectData(userData); и только после этого fetch фактически заполняет собственность.

Я так думаю? И как мне заполнить свойство в правильной итерации?

1 Ответ

1 голос
/ 23 апреля 2020

Ваша проблема в том, что вы не ждете, пока данные поступят для отправки их на сервер. Вы можете изменить рефакторинг getWeatherData и generate, чтобы сделать это так.

Прежде всего, нужно вернуть Promise из getWeatherData, чтобы вы могли ждать получения данных:

const getWeatherData = () => new Promise((resolve, reject) => {
  let zipInputValue = document.getElementById("zip").value;
  const weatherUrl = `http://api.openweathermap.org/data/2.5/weather?zip=${zipInputValue},${weatherCountryCode}&units=metric&appid=`;

  fetch(weatherUrl + weatherApiKey).then((res) => {
    if (res.status != 200) {
      console.log("Looks like there's been a problem.");
      return reject();
    }
    res.json().then((data) => {
      descriptionElement.innerText = "Weather: " + data["weather"][0]["description"];
      currenttempElement.innerText = "Temperature:" + data["main"]["temp"] + " °C";
      userData.temp = data["main"]["temp"];
      mintempElement.innerText = "Min.:" + data["main"]["temp_min"] + " °C";
      maxtempElement.innerText = "Max.:" + data["main"]["temp_max"] + " °C";

      resolve();
    });
  });  
  console.log(userData.temp);
});

Главное здесь было разрешить / отклонить обещание разрешить вызывающей функции (в данном случае generate), чтобы данные были выбраны.

Затем мы рефакторинг generate:

async function generate() {
  await getWeatherData();
  console.log("test");

  userData.date = newDate;
  userData.userResponse = getUserResponse();

  postProjectData(userData);

  getProjectData();
}

Идея состоит в том, чтобы преобразовать generate в асинхронную c функцию, чтобы заставить ее ждать поступления данных (getWeatherData) для вызова postProjectData.

...