Странное поведение при вставке скрипта в html - PullRequest
0 голосов
/ 14 марта 2020

Я хочу вставить 2 скрипта в секцию нижнего колонтитула html, но у меня странное поведение. Если я вставлю вручную, используя теги в самом html, он будет работать (index1. html). Но если я использую IIFE для создания тегов и вставки их в том же месте и в том же порядке (index2. html), в консоли отображается сообщение об ошибке «фиктивная переменная не определена». Здравый смысл говорит мне, что ошибка в порядке (потому что фиктивный определяется после его использования), но почему он работает для index1. html?

index1. html:

    ...
    <script src="script1.js" async></script>
    <script src="script2.js"></script>
    </body>
</html>

index2. html:

    ...
    <script>
        (function(){
            var loadScript = function(data, callback) {
                var script = document.createElement('script');
                script.src = data.src;
                if (data.opts) {
                    if (data.opts.async) script.async = data.opts.async;
                }
                document.body.appendChild(script);
            }

            var loadScriptRecursive = function(scripts, index) {
                loadScript(scripts[index], function () {
                    if (++index < scripts.length) loadScriptRecursive(scripts, index);
                });
            }

            var scripts = [{src: 'script1.js'}, {src: 'script2.js', opts: {async: false}}];
            loadScriptRecursive(scripts, 0);
        })()
    </script>

    </body>
</html>

script1. js:

$(document).ready(function () {
    if (dummy) ...
    ...
}

script2. js:

var dummy = true

1 Ответ

1 голос
/ 14 марта 2020

Прежде всего, вы декларируете callback, но никогда не использовали нас. Я предполагаю, что вы имеете в виду что-то вроде этого script.onload = callback;.

(function() {
  var loadScript = function(data, callback) {
    var script = document.createElement("script");
    script.src = data.src;
    script.onload = callback; // NEW LINE
    if (data.opts) {
      if (data.opts.async) script.async = data.opts.async;
    }
    document.body.appendChild(script);
  };

  var loadScriptRecursive = function(scripts, index) {
    loadScript(scripts[index], function() {
      if (++index < scripts.length) {
        loadScriptRecursive(scripts, index);
      }
    });
  };

  var scripts = [
    { src: "script1.js" },
    { src: "script2.js", opts: { async: false } }
  ];
  loadScriptRecursive(scripts, 0);
})();

Но этого недостаточно, чтобы решить эту проблему, из-за $(document).ready().

Давайте посмотрим, что говорят документы:

.ready Метод () предлагает способ запуска кода JavaScript, как только объектная модель документа (DOM) страницы станет безопасной для манипулирования. [jQuery]

Событие DOMContentLoaded возникает, когда исходный документ HTML был полностью загружен и проанализирован, не дожидаясь полной загрузки таблиц стилей, изображений и подкадров. [MDN]

В первом примере DOMContentLoaded срабатывает после загрузки JS файлов:

index.html perfomance results

Во втором примере DOMContentLoaded сработал немедленно, без ожидания файлов JS:

index2.html perfomance results


Именно поэтому вам нужно использовать $(window).on("load", function() {}); вместо $(document).ready(function() {});

...