【问题标题】:Fetch before DOM is ready Callback after DOM is readyDOM 准备好前获取 DOM 准备好后回调
【发布时间】:2020-10-06 09:23:22
【问题描述】:

背景

我正在使用 openweathermap 来显示曼彻斯特的当前温度和状况,代码运行良好。

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);

问题

因为我在 dom 准备好之后调用了 weatherBalloon 函数,所以 JS 使用从 api 接收的值更新默认 html 存在明显的延迟。

需要帮助

如何在 dom 准备好之前调用 fetch 并在 dom 准备好后让回调更新 html 以希望消除/减少更新 html 的可见延迟? 我尝试过使用 async 和 await 但无法正常工作 干杯!

【问题讨论】:

  • 我可能误解了帖子,但是只要您依赖从 dom 读取 cityID 和 APIkey 值,您就无法在 dom 加载之前真正调用该函数
  • fetch 返回一个你可以在任何地方等待的承诺。只需将(未等待的)结果(=promise)存储到某个变量中,稍后再存储await(或then)。
  • @SimenFjellstad 好点!当我将脚本(wordpress)排入队列时,我必须将它们硬编码到 JS 中,或者找出一种传递变量的方法。
  • @MarkusDresch 感谢您的建议。不幸的是,由于我目前对 javascript 的了解非常基础,因此我的深度不够。是否可以在 .then(function(data) { promise 中添加一个窗口事件监听器(页面加载)?

标签: javascript fetch


【解决方案1】:

你可以在任何你喜欢的地方等待一个承诺。你也可以在任何你喜欢的地方添加一个事件监听器,但是你必须处理事件已经发生的情况,尤其是当涉及到 DOM 就绪时。这是后一个选项的一个工作示例:

<html>
<body>

<script>
// more about docReady: https://*.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>

【讨论】:

  • 非常感谢,通过您提供的示例,我可以(几乎)理解发生了什么(我发现了一篇关于在函数前面放置感叹号的文章,但它正在发生需要一段时间来消化它)。喜欢 docReady 函数,它可以很好地检查 DOM 是否准备好。干杯!
  • !可以用很多东西代替,例如括号很常见。有关 IIFE 的更多信息:*.com/questions/592396