检查脚本的最佳实践是否已加载(并且对象存在于窗口空间中)?

问题描述 投票:1回答:1

This article帮助解释了浏览器如何引入脚本,但在尝试初始化之前检查对象的最佳做法是什么?

在这里链接headroom.js时,我正在检查窗口对象是否包含它。这没关系,还是应该使用某种形式的script.onload

<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>

<script defer>
        document.addEventListener('DOMContentLoaded', function(){
            // setup ScrollTrigger (animate when item comes into view)
            var trigger = new ScrollTrigger({
                offset: {x:0, y:300},
                once: true
            });


            // bind Headroom to nav
            if(window.Headroom){
                init_headroom();
            }else{
                console.log('polling for Headroom '+Date.now());
                let poll_for_headroom = window.setInterval(function(){
                    if(window.Headroom){
                        clearInterval(poll_for_headroom);
                        init_headroom();
                    }
                },20);
            }


更多问题:2a)这种轮询会阻止UI吗? 2b)我应该检查“ScrollTrigger.min.js”是否存在?

javascript parsing onload
1个回答
3
投票

最佳做法是将load处理程序添加到要检查其加载的script标记:

const headroomScript = document.querySelector('script[src*="headroom"]');
headroomScript.onload = () => {
  console.log('Loaded!');
  console.log(typeof window.Headroom);
};
<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>

要检查何时加载了所有多个脚本,可以使用Promise.all

// this will fail because the `src` of "js/main.js" does not exist in stack snippets:
const proms = [...document.querySelectorAll('script[src]')]
  .map(script => new Promise((resolve, reject) => {
    script.onload = resolve;
    script.onerror = reject;
  }));
Promise.all(proms)
  .then(() => {
    console.log('All scripts are loaded!');
    console.log(typeof window.Headroom);
  })
  .catch((err) => {
    console.log('There was an error');
  });
<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>

// this will succeed:
const proms = [...document.querySelectorAll('script[src][async]')]
  .map(script => new Promise((resolve, reject) => {
    script.onload = () => {
      console.log(script.src + ' loaded');
      resolve();
    };
    script.onerror = reject;
  }));
Promise.all(proms)
  .then(() => {
    console.log('All scripts are loaded!');
    console.log(typeof window.Headroom);
    console.log(typeof window.jQuery);
  })
  .catch((err) => {
    console.log('There was an error');
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" async></script>
<script src="https://unpkg.com/[email protected]/dist/headroom.min.js" async></script>

请注意,脚本的async属性仅对具有外部src的脚本有效 - 该属性对内联脚本没有影响,例如

<script async>
  // do some stuff
</script>

async标签在这里什么都不做。

这种方法和原始方法都不会阻止UI。

© www.soinside.com 2019 - 2024. All rights reserved.