异步/等待功能显示,等待,隐藏覆盖不工作在javascript中

nhaq1z21  于 2023-01-19  发布在  Java
关注(0)|答案(1)|浏览(118)

我遇到了一个问题,显示一个覆盖div元素,然后在runSearch()函数完成后再次隐藏它。简而言之,覆盖根本不显示。
如果叠加正常工作,它应该是什么样子:

如果我不得不猜测,我相信这可能与如何在javascript中正确实现async/await的误解有关。
由于篇幅有限,如果您需要更多的上下文,完整的Github项目可以作为一个完全部署的页面here来访问。
index.html中的覆盖div元素:

<div class="overlay d-flex justify-content-center align-items-center">
    <h5>Please wait...</h5>
    <div class="spinner-border" role="status">
      <span class="visually-hidden">Loading...</span>
    </div>
  </div>

CSS中的覆盖:

.overlay {
    background-color:#EFEFEF;
    position: fixed;
    width: 100%;
    height: 100%;
    z-index: 1000;
    left: 0px;
    display: none!important;
    /* without !important, the overlay would immediately kick into effect */
 }

调用时显示和隐藏覆盖层的JS函数:

function loadingOverlayOn() {
    document
      .getElementsByClassName("overlay")[0]
      .style.display = 'block'
  }
    function loadingOverlayOff() {
    document
      .getElementsByClassName("overlay")[0]
      .style.display = 'none'
  }

与按钮#1相关的JS:

cityInstanceBtn.addEventListener('click',async function(e){

    // for use in headings inside runSearch
    // reset
    globalCityName === null;
    globalCityState === null;
    globalCityCountry === null;

    globalCityName = e.target.dataset.city
    globalCityState = e.target.dataset.state
    globalCityCountry = e.target.dataset.country
    
    loadingOverlayOn();
    await runSearch(cityName, cityState, cityCountry, cityLat, cityLng, units)
    loadingOverlayOff();

})

关于按钮#2的JS,其发生在临时显示的Bootstrap模态内:

cityInstanceBtn.addEventListener('click', async function(){

            myModal.hide()

        globalCityName = document.getElementById(id).dataset.city
        globalCityState = document.getElementById(id).dataset.state
        globalCityCountry = document.getElementById(id).dataset.country

        loadingOverlayOn();
        await runSearch(cityName, cityState, cityCountry, cityLat, cityLng, units)
        loadingOverlayOff();
 
            
        })

JS函数,在此期间应显示覆盖,并在其执行完成后隐藏:

async function runSearch(
  cityName,
  cityState,
  country,
  cityLat,
  cityLng,
  detectedUnits
) {
  console.log("check cityState: " + cityState);
  console.log("check globalCityState: " + globalCityState);
  var h2Today = document.getElementById("today-title");
  var h2Next5Days = document.getElementById("next-5-days-title");

  if (globalCityState != "undefined" && globalCityName && globalCityCountry) {
    h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName}, ${globalCityState}, ${globalCityCountry}</span>`;
    h2Next5Days.innerHTML = `<span class="orange">4-day</span> outlook for <span class="cornflowerblue">${globalCityName}, ${globalCityState}, ${globalCityCountry}</span>`;
  } else if (
    (globalCityState = "undefined" && globalCityName && globalCityCountry)
  ) {
    h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName},${globalCityCountry}</span>`;
    h2Next5Days.innerHTML = `<span class="orange">4-day</span> outlook for <span class="cornflowerblue">${globalCityName}, ${globalCityCountry}</span>`;
  }

  var newSearchObject = {
    cityName: cityName,
    cityState: cityState,
    cityCountry: country,
    cityLat: cityLat,
    cityLng: cityLng,
    detectedUnits: detectedUnits,
  };

  var retrievedLocalStorage = localStorage.getItem("savedCities");
  retrievedLocalStorage = JSON.parse(retrievedLocalStorage);
  // const arr = retrievedLocalStorage.map(a => {a.cityLat, a.cityLng})

  if (retrievedLocalStorage === null) {
    localStorage.setItem("savedCities", JSON.stringify([newSearchObject]));

    generatePrevCitiesList();
  } else if (
    retrievedLocalStorage.length > 0 &&
    retrievedLocalStorage.length < 5
  ) {
    retrievedLocalStorage.reverse();

    if (
      !retrievedLocalStorage.some((s) => {
        return (
          s.cityLat == newSearchObject.cityLat &&
          s.cityLng == newSearchObject.cityLng
        );
      })
    ) {
      // Check if an array of objects contains another object: https://stackoverflow.com/a/63336477/9095603
      // this solution which converts objects to string first isn't entirely reliable if you can't guarantee the same order is preserved, for example: https://stackoverflow.com/a/201305/9095603

      retrievedLocalStorage.push(newSearchObject);

      retrievedLocalStorage.reverse();
      console.log("existingSearchObject2: " + retrievedLocalStorage);
      localStorage.setItem(
        "savedCities",
        JSON.stringify(retrievedLocalStorage)
      );
    }

    generatePrevCitiesList();
  } else if (retrievedLocalStorage.length >= 5) {
    retrievedLocalStorage.reverse();

    if (
      !retrievedLocalStorage.some((s) => {
        return (
          s.cityLat == newSearchObject.cityLat &&
          s.cityLng == newSearchObject.cityLng
        );
      })
    ) {
      retrievedLocalStorage.push(newSearchObject);
    }

    while (retrievedLocalStorage.length > 5) {
      retrievedLocalStorage.shift();
    }

    retrievedLocalStorage.reverse();
    localStorage.setItem("savedCities", JSON.stringify(retrievedLocalStorage));

    generatePrevCitiesList();
  }

  fetch(
    `https://api.openweathermap.org/data/2.5/forecast?lat=${cityLat}&lon=${cityLng}&units=${detectedUnits}&appid=${apiKey}`
  )
    .then((response) => response.json())
    .then((data) => {
      console.log(data);
      console.table(data.list);
      console.log(JSON.stringify(data));

      var timezone = data.city.timezone;
      console.log({ timezone });
      var country = data.city.country;
      console.log({ country });
      var cityName = data.city.name;
      console.log({ cityName });

      var datesArray = [];
      console.log({ datesArray });

      const days = [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
      ];
      // var h2Today = document.getElementById('today-title')

      //     h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName}, ${globalCityState}, ${globalCityCountry}</span>`
      // }
      //     h2Today.innerHTML = `<span class="orange">Today's</span> forecast for <span class="cornflowerblue">${globalCityName},${globalCityCountry}</span>`
      // }

      for (let i = 0; i < data.list.length; i++) {
        var unixTimestamp = data.list[i].dt;
        console.log(data.list[i].dt);
        // you don't need it for dt_txt but if you want to use the unix timestamp in the data, you can do this conversion:

        var jsTimestamp = unixTimestamp * 1000;
        var date = new Date(jsTimestamp);
        var basicDateLocalAU = date.toLocaleDateString("en-AU");
        var basicDateLocalUS = date.toLocaleDateString("en-US");
        var basicDateLocalUser = date.toLocaleDateString(`en-${country}`);

        console.log(basicDateLocalAU); // Prints: 5/6/2022
        console.log(basicDateLocalUS); // Prints: 6/5/2022
        console.log(basicDateLocalUser); // Prints: 6/5/2022

        var timeLocalAU = date.toLocaleTimeString("en-AU", {
          hour: "2-digit",
          minute: "2-digit",
        }); // Prints: 13:10:34
        // https://stackoverflow.com/a/20430558/9095603
        // https://bobbyhadz.com/blog/javascript-typeerror-date-getday-is-not-a-function#:~:text=getDay%20is%20not%20a%20function%22%20error%20occurs%20when%20the%20getDay,method%20on%20valid%20date%20objects.

        data.list[i].basicDateLocalAU = basicDateLocalAU;
        data.list[i].basicDateLocalUS = basicDateLocalUS;
        data.list[i].basicDateLocalUser = basicDateLocalUser;
        data.list[i].dayOfWeekIndex = date.getDay();
        data.list[i].dayOfWeekValue = days[date.getDay()];
        data.list[i].basicTime = timeLocalAU;

        // https://bobbyhadz.com/blog/javascript-array-push-if-not-exist

        if (!datesArray.includes(basicDateLocalUser)) {
          datesArray.push(basicDateLocalUser);

          var dayOfWeek = days[date.getDay()];
          console.log(dayOfWeek);
        }
      }

      console.log({ date });

      console.log({ data });

      var datalist = data.list;
      console.log({ datalist });

      var obj = groupBy(datalist, "basicDateLocalAU");
      console.log({ obj });
      // const result = data.list.group(({ basicCalendarDateAU }) => basicCalendarDateAU);

      for (let i = 0; i < obj.length; i++) {
        var dayTableEle = document.querySelector(`#day${i} table`);
        // var textNode = document.createTextNode(`${dayOfWeekValue}`);

        dayTableEle.innerHTML = `<row><th>Time</th><th>Temp</th><th></th><th>Conditions</th><th>Humidity</th><th>Wind speed</th></row>`;
        for (let j = 0; j < obj[i].length; j++) {
          console.log(obj[i].length);
          if (!document.querySelector(`#day${i} h5`).innerText) {
            document.querySelector(
              `#day${i} h5`
            ).innerText = `${obj[i][j].dayOfWeekValue}`;
          }
          if (
            !document.querySelector(`#day${i} span#usercountry-dateformat`)
              .innerText
          ) {
            document.querySelector(
              `#day${i} span#usercountry-dateformat`
            ).innerText = `${obj[i][j].basicDateLocalUser}`;
          }
          if (
            !document.querySelector(`#day${i} span#AU-dateformat`).innerText
          ) {
            document.querySelector(
              `#day${i} span#AU-dateformat`
            ).innerText = `${obj[i][j].basicDateLocalAU}`;
            document
              .querySelector(`#day${i} span#AU-dateformat`)
              .style.setProperty("display", "none");
          }
          if (
            !document.querySelector(`#day${i} span#US-dateformat`).innerText
          ) {
            document.querySelector(
              `#day${i} span#US-dateformat`
            ).innerText = `${obj[i][j].basicDateLocalUS}`;
            document
              .querySelector(`#day${i} span#US-dateformat`)
              .style.setProperty("display", "none");
          }
          // var kelvinToCelcius = obj[i][j].main.temp - 273.15;

          var tempMetric;
          var tempImperial;

          var windSpeedImperial;
          var windSpeedMetric;

          if (units == "metric") {
            var tempMetric = obj[i][j].main.temp;
            tempMetric = roundedToFixed(tempMetric, 1);
            var tempImperial = tempMetric * 1.8 + 32;
            tempImperial = roundedToFixed(tempImperial, 1);

            var windSpeedMetric = obj[i][j].wind.speed;
            windSpeedMetric = roundedToFixed(windSpeedMetric, 1);
            var windSpeedImperial = windSpeedMetric * 2.23694;
            windSpeedImperial = roundedToFixed(windSpeedImperial, 1);

            var metricDisplay = "inline";
            var imperialDisplay = "none";
          } else if (units == "imperial") {
            var tempImperial = obj[i][j].main.temp;
            tempImperial = roundedToFixed(tempImperial, 1);
            var tempMetric = (tempImperial - 32) / 1.8;
            tempMetric = roundedToFixed(tempMetric, 1);

            var windSpeedImperial = obj[i][j].wind.speed;
            windSpeedImperial = roundedToFixed(windSpeedImperial, 1);
            var windSpeedMetric = windSpeedImperial / 2.23694;
            windSpeedMetric = roundedToFixed(windSpeedMetric, 1);

            var metricDisplay = "none";
            var imperialDisplay = "inline";
          }

          dayTableEle.innerHTML += `
            <row>
                <td id="tdTime">${obj[i][j].basicTime}</td>
                <td id="tdTemp">
                    <span class="temp-metric metric" style="display:${metricDisplay};">${tempMetric} ${tempUnitsMetric}</span>
                    <span class="temp-imperial imperial" style="display:${imperialDisplay};">${tempImperial} ${tempUnitsImperial}</span>
                </td>
                <td><img src="https://openweathermap.org/img/wn/${obj[i][j].weather[0].icon}.png" alt="weather icon"></td>
                <td id="tdConditions">${obj[i][j].weather[0].description}</td>
                <td id="tdHumidity">${obj[i][j].main.humidity} %</td>
                <td id="tdWindSpeed">
                    <span class="windspeed-metric metric" style="display:${metricDisplay};">${windSpeedMetric} ${windSpeedUnitsMetric}</span>
                    <span class="windspeed-imperial imperial" style="display:${imperialDisplay};">${windSpeedImperial} ${windSpeedUnitsImperial}</span>
                </td>
                <td id="tdWindDir"><i style="transform: rotate(${obj[i][j].wind.deg}deg)" class="fa-solid fa-arrow-up"></i></td>
            </row>
            `;
        }
      }


    });

}

我们可以看到,事件侦听器已正确连接-这两个按钮都是如此,但我将在这里显示一个,仅作为代表:

完整的Github项目可以作为完全部署的页面here访问。
重申一下,问题是在这一系列事件中,覆盖根本不出现,而且在页面构建之前,我过早地看到了页面元素:

loadingOverlayOn();
    await runSearch(cityName, cityState, cityCountry, cityLat, cityLng, units)
    loadingOverlayOff();
bjg7j2ky

bjg7j2ky1#

您不是在等待fetch,而是在使用then。
你必须等待fetch
参见以下示例

const response = await fetch(url);
const jsonData = await response.json()

相关问题