2

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!

philip
  • 403
  • 1
  • 4
  • 14
  • 2
    I may have misinterpreted the post, but as long as you're relying on reading the cityID and APIkey values from the dom, you can't really call the function before the dom has loaded – Simen Fjellstad Oct 06 '20 at 09:28
  • `fetch` returns a promise that you can await anywhere. simply store the (not awaited) result (=promise) into some variable and `await` (or `then`) it later on. – Markus Dresch Oct 06 '20 at 09:30
  • @SimenFjellstad good point! I'd have to hardcode those into the JS or figure out a way of passing the variables when I enqueue the script (wordpress). – philip Oct 06 '20 at 13:40
  • @MarkusDresch thanks for the suggestion. Unfortunately I'm out of my depth as my knowledge at the moment with javascript is very basic. is it possible to add a window event listener (page loaded) inside the .then(function(data) { promise? – philip Oct 06 '20 at 13:46

1 Answers1

2

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>
Markus Dresch
  • 5,290
  • 3
  • 20
  • 40
  • thank you so much, with the example you've given I can (almost) understand what is going on (I've found an article about putting an exclamation mark in front of a function but it's going to take a while to digest it). Love the docReady function which nicely takes care of checking whether the DOM is ready or not. Cheers! – philip Oct 07 '20 at 11:53
  • the ! can be replaced with many things, parenthesis are very common for example. more info about IIFE: https://stackoverflow.com/questions/592396 – Markus Dresch Oct 07 '20 at 12:50