Лучшая практика для проверки загрузки скрипта (и объект существует в пространстве окна)? - PullRequest
1 голос
/ 20 марта 2019

Эта статья помогла объяснить, как браузер загружает скрипты, но как лучше проверить, существует ли объект, прежде чем пытаться его инициализировать?

При связывании headroom.js здесь, я в настоящее время проверяю, содержит ли объект окна это. Это нормально, или я должен использовать какую-то форму script.onload ?

<script src="js/main.js"></script>
<script src="js/libs/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/headroom.js@0.9.4/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) Будет ли этот вид пользовательского интерфейса избирательного блока? 2b) Должен ли я проверять, существует ли ScrollTrigger.min.js?

1 Ответ

3 голосов
/ 20 марта 2019

Рекомендуется добавить обработчик 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/headroom.js@0.9.4/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/headroom.js@0.9.4/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/headroom.js@0.9.4/dist/headroom.min.js" async></script>

Обратите внимание, что атрибут async для сценариев эффективен только для сценариев с внешним src - атрибут не влияет на встроенные сценарии, например,

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

тег async здесь ничего не даст.

Ни этот подход, ни ваш оригинальный подход не будут блокировать пользовательский интерфейс.

...