Fetch before DOM is ready Callback after DOM is ready

Viewed 852

Background

I'm using openweathermap to display the current temp and condition of Manchester, the code is working great.

HTML

<div class="wp-block-pbf-block-weather" data-key="*******************" data-city="2643123">
    <p>The Current Weather in <span id="city">Manchester</span> 
        is <span id="temp">probably 13</span>°C 
        with <span id="condition">doom and gloom</span>
    </p>
</div>

Javascript

function weatherBalloon( cityID, APIkey ) {
    fetch('https://api.openweathermap.org/data/2.5/weather?id=' + cityID+ '&appid=' + APIkey)
    .then(function(resp) { if (!resp.ok) {
    throw new Error('Network response was not ok');
    }
    return resp.json() }) // Convert data to json
    .then(function(data) {

        document.getElementById("temp").innerHTML = Math.round(data.main.temp - 273.15);
        document.getElementById("condition").innerHTML = data.weather[0].description;
        console.log(data);

        var cat = "part_cloud"; // set default weather category
        var id = data.weather[0].id;
        if (id >= 200 && id <= 299) { cat = "thunder"};
        if (id >= 300 && id <= 399) { cat = "rain"};
        if (id >= 500 && id <= 531) { cat = "rain"};
        if (id >= 600 && id <= 699) { cat = "snow"};
        if (id >= 700 && id <= 799) { cat = "fog"};
        if (id == 800 ) { cat = "sun"};
        if (id >= 801 && id <= 802) { cat = "part_cloud"};
        if (id >= 803 && id <= 804) { cat = "cloud"};

        var video = window.location.origin + "/wp-content/uploads/bg_video_" + cat + ".mp4";
        console.log(video);
    })
    .catch(error => {
        console.error('There has been a problem with your fetch operation:', error);
        console.log ("OH NO Something Has Gone Wrong!")
    });
}



(function($){
    $(document).ready( function(){
        var cityID = $('.wp-block-pbf-block-weather').data('city');
        var APIkey = $('.wp-block-pbf-block-weather').data('key');
        weatherBalloon( cityID, APIkey );

    });



})(jQuery);

Problem

Because I'm calling the weatherBalloon function after the dom is ready there is a visible delay with the JS updating the default html with the values received from the api.

HELP NEEDED

How can I call the fetch before the dom is ready and have the callback update the html after the dom is ready so as to hopefully remove / reduce the visible delay in updating the html? I've tried playing with async and await but couldn't get anything to work Cheers!

1 Answers

You can await a promise anywhere you like. You can also add an event listener anywhere you like, but you'll have to handle the case where the event already happened, especially when it comes to DOM ready. Here's a working example for the latter option:

<html>
<body>

<script>
// more about docReady: https://stackoverflow.com/questions/9899372/
function docReady(fn) {
  if (document.readyState === "complete" || document.readyState === "interactive") {
    console.log('document already ready');
    setTimeout(fn, 1);
  } else {
    console.log('adding event listener');
    document.addEventListener("DOMContentLoaded", fn);
  }
}

// the function to be called on "DOM ready"
function showData(data) {
  const output = document.getElementById('output');
  output.innerHTML = JSON.stringify(data);
}

// self executing function (async/await style)
!async function() {
  const response  = await fetch('https://jsonplaceholder.typicode.com/todos/1');
  const data = await response.json();

  console.log(data);
  docReady(showData(data));
}();
</script>

<div id="output"></div>

</body>
</html>
Related