Сведения о вопросе

Kimsanov

20:54, 16th August, 2020

Теги

javascript   file   import   include    

Динамическая загрузка файла JavaScript

Просмотров: 763   Ответов: 24

Как можно надежно и динамически загрузить файл JavaScript? Это будет использоваться для реализации модуля или компонента, который при 'initialized' компонент будет динамически загружать все необходимые сценарии библиотеки JavaScript по требованию.

Клиент, использующий компонент, не обязан загружать все файлы сценариев библиотеки (и вручную вставлять теги <script> на их веб-страницу), реализующие этот компонент - только файл сценария компонента 'main'.

Как сделать это в обычных библиотеках JavaScript (прототип, jQuery и т. д.)? Объединяют ли эти инструменты несколько файлов JavaScript в одну распространяемую версию файла сценария 'build'? Или они делают какую-либо динамическую загрузку вспомогательных скриптов 'library'?

Дополнение к этому вопросу: есть ли способ обработать событие после загрузки динамически включаемого файла JavaScript? Прототип имеет document.observe для событий всего документа. Пример:

document.observe("dom:loaded", function() {
  // initially hide all containers for tab content
  $$('div.tabcontent').invoke('hide');
});

Каковы доступные события для элемента сценария?



  Сведения об ответе

+-*/

00:55, 21st August, 2020

Вы можете написать динамические теги скриптов (используя прототип ):

new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});

Проблема здесь заключается в том, что мы не знаем, когда внешний файл скрипта будет полностью загружен.

Мы часто хотим, чтобы наш зависимый код был на самой следующей строке и хотели бы написать что-то вроде:

if (iNeedSomeMore) {
    Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
    myFancyMethod(); // cool, no need for callbacks!
}

Существует умный способ ввести зависимости скриптов без необходимости обратных вызовов. Вам просто нужно вытащить скрипт через синхронный запрос AJAX и оценить скрипт на глобальном уровне.

При использовании прототипа метод Script.load выглядит следующим образом:

var Script = {
    _loadedScripts: [],
    include: function(script) {
        // include script only once
        if (this._loadedScripts.include(script)) {
            return false;
        }
        // request file synchronous
        var code = new Ajax.Request(script, {
            asynchronous: false,
            method: "GET",
            evalJS: false,
            evalJSON: false
        }).transport.responseText;
        // eval code on global level
        if (Prototype.Browser.IE) {
            window.execScript(code);
        } else if (Prototype.Browser.WebKit) {
            $$("head").first().insert(Object.extend(
                new Element("script", {
                    type: "text/javascript"
                }), {
                    text: code
                }
            ));
        } else {
            window.eval(code);
        }
        // remember included script
        this._loadedScripts.push(script);
    }
};


  Сведения об ответе

ASSembler

14:43, 20th August, 2020

В javascript нет import / include / require, но есть два основных способа достичь желаемого:

1-Вы можете загрузить его с помощью вызова AJAX, а затем использовать eval.

Это самый простой способ, но он ограничен вашим доменом из-за настроек безопасности Javascript, и использование eval открывает дверь для ошибок и взломов.

2-Добавьте тег script со скриптом URL в HTML.

Определенно, это лучший способ уйти. Вы можете загрузить скрипт даже с внешнего сервера, и он чист, поскольку вы используете анализатор браузера для оценки кода. Вы можете поместить тег в начале веб-страницы или в нижней части тела.

Оба эти решения обсуждаются и иллюстрируются здесь.

Теперь, есть большая проблема, о которой вы должны знать. Это означает, что вы удаленно загружаете код. Современные веб-браузеры загружают файл и продолжают выполнять ваш текущий сценарий, потому что они загружают все асинхронно, чтобы улучшить производительность.

Это означает, что если вы используете эти приемы непосредственно, вы не сможете использовать свой недавно загруженный код в следующей строке после того, как вы попросили его загрузить, потому что он все еще будет загружаться.

E.G : my_lovely_script.js содержит MySuperObject

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

Затем вы перезагрузите страницу, нажав F5. И это работает! Запутанным...

Так что же с этим делать ?

Ну, вы можете использовать Хак, предложенный автором в ссылке, которую я вам дал. Таким образом, для людей в спешке он использует En event для запуска функции обратного вызова при загрузке скрипта. Таким образом, вы можете поместить весь код с помощью удаленной библиотеки в функцию обратного вызова. E.G :

function loadScript(url, callback)
{
    // adding the script tag to the head as suggested before
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = url;

   // then bind the event to the callback function 
   // there are several events for cross browser compatibility
   script.onreadystatechange = callback;
   script.onload = callback;

   // fire the loading
   head.appendChild(script);
}

Затем вы пишете код, который хотите использовать AFTER скрипт загружается в функцию lambda :

var myPrettyCode = function() {
    // here, do what ever you want
};

А потом ты все это запустишь :

loadScript("my_lovely_script.js", myPrettyCode);

Ладно, я все понял. Но писать все это-сплошная мука.

Ну, в таком случае, вы можете использовать, как всегда, фантастический фреймворк free jQuery, который позволяет вам делать то же самое в одной строке :

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});


  Сведения об ответе

PAGE

20:59, 19th August, 2020

Недавно я использовал гораздо менее сложную версию с jQuery :

<script src="scripts/jquery.js"></script>
<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  var $head = $("head");
  for (var i = 0; i < js.length; i++) {
    $head.append("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>

Он отлично работал в каждом браузере, в котором я его тестировал: IE6/7, Firefox, Safari, Opera.

Обновление: jQuery-менее версия:

<script>
  var js = ["scripts/jquery.dimensions.js", "scripts/shadedborder.js", "scripts/jqmodal.js", "scripts/main.js"];
  for (var i = 0, l = js.length; i < l; i++) {
    document.getElementsByTagName("head")[0].innerHTML += ("<script src=\"" + js[i] + "\"></scr" + "ipt>");
  }
</script>


  Сведения об ответе

padenie

07:37, 26th August, 2020

Я сделал в основном то же самое, что и вы Adam, но с небольшой модификацией, чтобы убедиться, что я добавляю к тегу head, чтобы выполнить работу. Я просто создал функцию include (код ниже) для обработки как скрипта, так и файлов css.

Эта функция также проверяет, чтобы убедиться, что скрипт или файл CSS еще не был загружен динамически. Он не проверяет значения, закодированные вручную, и, возможно, был лучший способ сделать это, но он служил этой цели.

function include( url, type ){
    // First make sure it hasn't been loaded by something else.
    if( Array.contains( includedFile, url ) )
        return;

    // Determine the MIME-type
    var jsExpr = new RegExp( "js$", "i" );
    var cssExpr = new RegExp( "css$", "i" );
    if( type == null )
        if( jsExpr.test( url ) )
            type = 'text/javascript';
        else if( cssExpr.test( url ) )
            type = 'text/css';

    // Create the appropriate element.
    var tag = null;
    switch( type ){
        case 'text/javascript' :
            tag = document.createElement( 'script' );
            tag.type = type;
            tag.src = url;
            break;
        case 'text/css' :
            tag = document.createElement( 'link' );
            tag.rel = 'stylesheet';
            tag.type = type;
            tag.href = url;
            break;
    }

    // Insert it to the <head> and the array to ensure it is not
    // loaded again.
    document.getElementsByTagName("head")[0].appendChild( tag );
    Array.add( includedFile, url );
}


  Сведения об ответе

ITSME

06:27, 27th August, 2020

еще один удивительный ответ

$.getScript("my_lovely_script.js", function(){


   alert("Script loaded and executed.");
  // here you can use anything you defined in the loaded script

 });

https://stackoverflow.com/a/950146/671046


  Сведения об ответе

lool

05:29, 9th August, 2020

Вот несколько примеров кода, которые я нашел... у кого-нибудь есть лучший способ?

  function include(url)
  {
    var s = document.createElement("script");
    s.setAttribute("type", "text/javascript");
    s.setAttribute("src", url);
    var nodes = document.getElementsByTagName("*");
    var node = nodes[nodes.length -1].parentNode;
    node.appendChild(s);
  }


  Сведения об ответе

SSESION

19:52, 26th August, 2020

Если вы уже загрузили jQuery, вы должны использовать $.getScript .

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


  Сведения об ответе

pumpa

20:04, 28th August, 2020

у кого-нибудь есть лучший способ?

Я думаю, что просто добавить скрипт в тело было бы проще, чем добавить его в последний узел на странице. Как насчет этого:

function include(url) {
  var s = document.createElement("script");
  s.setAttribute("type", "text/javascript");
  s.setAttribute("src", url);
  document.body.appendChild(s);
}


  Сведения об ответе

ITSME

20:51, 18th August, 2020

я использовал еще одно решение, которое нашел в сети ... эта функция находится в разделе creativecommons и проверяет, был ли включен источник перед вызовом функции ...

вы можете найти этот файл здесь: include.js

/** include - including .js files from JS - bfults@gmail.com - 2005-02-09
 ** Code licensed under Creative Commons Attribution-ShareAlike License 
 ** http://creativecommons.org/licenses/by-sa/2.0/
 **/              
var hIncludes = null;
function include(sURI)
{   
  if (document.getElementsByTagName)
  {   
    if (!hIncludes)
    {
      hIncludes = {}; 
      var cScripts = document.getElementsByTagName("script");
      for (var i=0,len=cScripts.length; i < len; i++)
        if (cScripts[i].src) hIncludes[cScripts[i].src] = true;
    }
    if (!hIncludes[sURI])
    {
      var oNew = document.createElement("script");
      oNew.type = "text/javascript";
      oNew.src = sURI;
      hIncludes[sURI]=true;
      document.getElementsByTagName("head")[0].appendChild(oNew);
    }
  }   
} 


  Сведения об ответе

darknet

10:24, 9th August, 2020

Только что узнал о замечательной функции в YUI 3 (на момент написания доступно в предварительном выпуске). Вы можете легко вставить зависимости в библиотеки YUI и модули "external" (то, что вы ищете) без слишком большого количества кода: YUI Loader .

Он также отвечает на ваш второй вопрос относительно функции, вызываемой сразу же после загрузки внешнего модуля.

Пример:

YUI({
    modules: {
        'simple': {
            fullpath: "http://example.com/public/js/simple.js"
        },
        'complicated': {
            fullpath: "http://example.com/public/js/complicated.js"
            requires: ['simple']  // <-- dependency to 'simple' module
        }
    },
    timeout: 10000
}).use('complicated', function(Y, result) {
    // called as soon as 'complicated' is loaded
    if (!result.success) {
        // loading failed, or timeout
        handleError(result.msg);
    } else {
        // call a function that needs 'complicated'
        doSomethingComplicated(...);
    }
});

Отлично работал для меня и имеет преимущество в управлении зависимостями. См. документацию YUI для примера с календарем YUI 2 .


  Сведения об ответе

PAGE

14:43, 28th August, 2020

Если вы хотите загрузить сценарий SYNC , вам нужно добавить текст сценария непосредственно в тег HTML HEAD. Добавление его как вызовет загрузку ASYNC . Чтобы синхронно загрузить текст скрипта из внешнего файла, используйте XHR. Ниже приведен краткий пример (он использует части других ответов в этом и других сообщениях):

/*sample requires an additional method for array prototype:*/

if (Array.prototype.contains === undefined) {
Array.prototype.contains = function (obj) {
    var i = this.length;
    while (i--) { if (this[i] === obj) return true; }
    return false;
};
};

/*define object that will wrap our logic*/
var ScriptLoader = {
LoadedFiles: [],

LoadFile: function (url) {
    var self = this;
    if (this.LoadedFiles.contains(url)) return;

    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                self.LoadedFiles.push(url);
                self.AddScript(xhr.responseText);
            } else {
                if (console) console.error(xhr.statusText);
            }
        }
    };
    xhr.open("GET", url, false);/*last parameter defines if call is async or not*/
    xhr.send(null);
},

AddScript: function (code) {
    var oNew = document.createElement("script");
    oNew.type = "text/javascript";
    oNew.textContent = code;
    document.getElementsByTagName("head")[0].appendChild(oNew);
}
};

/*Load script file. ScriptLoader will check if you try to load a file that has already been loaded (this check might be better, but I'm lazy).*/

ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
ScriptLoader.LoadFile("Scripts/jquery-2.0.1.min.js");
/*this will be executed right after upper lines. It requires jquery to execute. It requires a HTML input with id "tb1"*/
$(function () { alert($('#tb1').val()); });


  Сведения об ответе

PHPH

11:43, 8th August, 2020

jquery решил это за меня со своим .Функция append()-используется для загрузки полного пакета пользовательского интерфейса jquery

/*
 * FILENAME : project.library.js
 * USAGE    : loads any javascript library
 */
    var dirPath = "../js/";
    var library = ["functions.js","swfobject.js","jquery.jeditable.mini.js","jquery-ui-1.8.8.custom.min.js","ui/jquery.ui.core.min.js","ui/jquery.ui.widget.min.js","ui/jquery.ui.position.min.js","ui/jquery.ui.button.min.js","ui/jquery.ui.mouse.min.js","ui/jquery.ui.dialog.min.js","ui/jquery.effects.core.min.js","ui/jquery.effects.blind.min.js","ui/jquery.effects.fade.min.js","ui/jquery.effects.slide.min.js","ui/jquery.effects.transfer.min.js"];

    for(var script in library){
        $('head').append('<script type="text/javascript" src="' + dirPath + library[script] + '"></script>');
    }

Чтобы использовать - в голове вашего html/php/etc после того, как вы import jquery.js, вы просто включили бы этот файл, как таковой, чтобы загрузить всю вашу библиотеку, добавив ее к голове...

<script type="text/javascript" src="project.library.js"></script>


  Сведения об ответе

lesha

19:39, 3rd August, 2020

Метод, который мы используем на работе, заключается в том, чтобы запросить файл javascript, используя запрос AJAX, а затем eval() возврат. Если вы используете библиотеку прототипов,они поддерживают эту функцию в своем вызове Ajax.Request.


  Сведения об ответе

9090

11:29, 22nd August, 2020

Держите его красивым, коротким, простым и ремонтопригодным! :]

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

Этот код-просто короткий функциональный пример, который может потребовать дополнительной функциональности функции для полной поддержки на любой (или данной) платформе.


  Сведения об ответе

prince

13:55, 25th August, 2020

Есть новый предлагаемый стандарт ECMA под названием dynamic import, недавно включенный в Chrome и Safari.

const moduleSpecifier = './dir/someModule.js';

import(moduleSpecifier)
   .then(someModule => someModule.foo()); // executes foo method in someModule


  Сведения об ответе

PIRLO

01:11, 11th August, 2020

Есть скрипты, которые разработаны специально для этой цели.

yepnope.js встроен в Modernizr, а lab.js является более оптимизированной (но менее удобной для пользователя версией.

Я бы не рекомендовал делать это через большую библиотеку, такую как jquery или прототип, потому что одним из главных преимуществ загрузчика сценариев является возможность загружать сценарии рано - вам не нужно ждать, пока jquery & все ваши элементы dom загрузятся, прежде чем запускать проверку, чтобы увидеть, хотите ли вы динамически загрузить сценарий.


  Сведения об ответе

JUST___

22:01, 3rd August, 2020

Я написал простой модуль, который автоматизирует работу по импорту / включению скриптов модулей в JavaScript. Дайте ему попробовать и, пожалуйста, пощадите некоторые отзывы! :) Для детального объяснения кода обратитесь к этой записи в блоге: http://stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/

var _rmod = _rmod || {}; //require module namespace
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark the root directory of your library, any library


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };

    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(script_name) {
    var np = script_name.split('.');
    if (np[np.length-1] === '*') {
        np.pop();
        np.push('_all');
    }

    script_name = np.join('.');
    var uri = _rmod.libpath + np.join('/')+'.js';
    if (!_rmod.loading.scripts.hasOwnProperty(script_name) 
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri, 
            _rmod.requireCallback, 
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

// ----- USAGE -----

require('ivar.util.array');
require('ivar.util.string');
require('ivar.net.*');

ready(function(){
    //do something when required scripts are loaded
});


  Сведения об ответе

COOL

21:06, 10th August, 2020

Я теряюсь во всех этих образцах, но сегодня мне нужно было загрузить внешний .js из моего основного .js, и я сделал это:

document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");


  Сведения об ответе

PROGA

16:39, 14th August, 2020

Вот простой вариант с обратным вызовом и поддержкой IE:

function loadScript(url, callback) {

    var script = document.createElement("script")
    script.type = "text/javascript";

    if (script.readyState) { //IE
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" || script.readyState == "complete") {
                script.onreadystatechange = null;
                callback();
            }
        };
    } else { //Others
        script.onload = function () {
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

loadScript("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

     //jQuery loaded
     console.log('jquery loaded');

});


  Сведения об ответе

lool

21:44, 23rd August, 2020

Абсурдная однострочка для тех, кто считает, что загрузка библиотеки js не должна занимать более одной строки кода: P

await new Promise((resolve, reject) => {let js = document.createElement("script"); js.src="mylibrary.js"; js.onload=resolve; js.onerror=reject; document.body.appendChild(js)});

Очевидно, что если скрипт, который вы хотите import, является модулем, вы можете использовать функцию import(...) .


  Сведения об ответе

darknet

07:45, 23rd August, 2020

Вот простой пример для функции загрузки JS файлов. Соответствующая точка:

  • вам не нужно jQuery, поэтому вы можете использовать это изначально, чтобы загрузить также файл jQuery.js
  • это асинхронно с обратным вызовом
  • это гарантирует, что он загружается только один раз, так как он сохраняет приложение с записью загруженных URL-адресов, что позволяет избежать использования сети
  • в отличие от jQuery $.ajax или $.getScript вы можете использовать nonces, решая таким образом проблемы с CSP unsafe-inline . Просто используйте свойство script.nonce
var getScriptOnce = function() {

    var scriptArray = []; //array of urls (closure)

    //function to defer loading of script
    return function (url, callback){
        //the array doesn't have such url
        if (scriptArray.indexOf(url) === -1){

            var script=document.createElement('script');
            script.src=url;
            var head=document.getElementsByTagName('head')[0],
                done=false;

            script.onload=script.onreadystatechange = function(){
                if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
                    done=true;
                    if (typeof callback === 'function') {
                        callback();
                    }
                    script.onload = script.onreadystatechange = null;
                    head.removeChild(script);

                    scriptArray.push(url);
                }
            };

            head.appendChild(script);
        }
    };
}();

Теперь вы используете его просто путем

getScriptOnce("url_of_your_JS_file.js");


  Сведения об ответе

nYU

06:28, 25th August, 2020

все основные библиотеки javascript, такие как jscript, prototype, YUI, поддерживают загрузку файлов сценариев. Например, в YUI после загрузки ядра можно выполнить следующие действия для загрузки элемента управления calendar

var loader = new YAHOO.util.YUILoader({

    require: ['calendar'], // what components?

    base: '../../build/',//where do they live?

    //filter: "DEBUG",  //use debug versions (or apply some
                        //some other filter?

    //loadOptional: true, //load all optional dependencies?

    //onSuccess is the function that YUI Loader
    //should call when all components are successfully loaded.
    onSuccess: function() {
        //Once the YUI Calendar Control and dependencies are on
        //the page, we'll verify that our target container is 
        //available in the DOM and then instantiate a default
        //calendar into it:
        YAHOO.util.Event.onAvailable("calendar_container", function() {
            var myCal = new YAHOO.widget.Calendar("mycal_id", "calendar_container");
            myCal.render();
        })
     },

    // should a failure occur, the onFailure function will be executed
    onFailure: function(o) {
        alert("error: " + YAHOO.lang.dump(o));
    }

 });

// Calculate the dependency and insert the required scripts and css resources
// into the document
loader.insert();


  Сведения об ответе

ASER

18:00, 5th August, 2020

Я знаю, что мой ответ немного запоздал для этого вопроса, но вот отличная статья в www.html5rocks.com - глубокое погружение в мутные воды загрузки скриптов .

В этой статье делается вывод, что с точки зрения поддержки браузера, лучшим способом динамической загрузки файла JavaScript без блокировки рендеринга контента является следующий способ:

Учитывая, что у вас есть четыре скрипта с именем script1.js, script2.js, script3.js, script4.js , то вы можете сделать это с применением async = false :

[
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

Теперь спец говорит: загружайте вместе, выполняйте по порядку, как только все загрузятся.

Firefox < 3.6, Opera говорит: Я понятия не имею, что это такое “async”, но так уж получилось, что я выполняю скрипты, добавленные через JS, в том порядке, в котором они добавлены.

Safari 5.0 говорит: Я понимаю “async”, но не понимаю, как установить его на “false” с JS. Я выполню ваши сценарии, как только они приземлятся, в любом порядке.

IE < 10 говорит: нет понятия о “async”, но есть обходной путь с использованием “onreadystatechange”.

Все остальное говорит: Я твой друг,мы будем делать это по правилам.

Теперь полный код с IE < 10 обходным путем:

var scripts = [
  'script1.js',
  'script2.js',
  'script3.js',
  'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];

// Watch scripts load in IE
function stateChange() {
  // Execute as many scripts in order as we can
  var pendingScript;
  while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
    pendingScript = pendingScripts.shift();
    // avoid future loading events from this script (eg, if src changes)
    pendingScript.onreadystatechange = null;
    // can't just appendChild, old IE bug if element isn't closed
    firstScript.parentNode.insertBefore(pendingScript, firstScript);
  }
}

// loop through our script urls
while (src = scripts.shift()) {
  if ('async' in firstScript) { // modern browsers
    script = document.createElement('script');
    script.async = false;
    script.src = src;
    document.head.appendChild(script);
  }
  else if (firstScript.readyState) { // IE<10
    // create a script and add it to our todo pile
    script = document.createElement('script');
    pendingScripts.push(script);
    // listen for state changes
    script.onreadystatechange = stateChange;
    // must set src AFTER adding onreadystatechange listener
    // else we’ll miss the loaded event for cached scripts
    script.src = src;
  }
  else { // fall back to defer
    document.write('<script src="' + src + '" defer></'+'script>');
  }
}

Несколько трюков и минификация позже, это 362 байта

!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
  "//other-domain.com/1.js",
  "2.js"
])


  Сведения об ответе

PIRLO

16:58, 5th August, 2020

Что-то вроде этого...

<script>
     $(document).ready(function() {
          $('body').append('<script src="https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places&callback=getCurrentPickupLocation" async defer><\/script>');
     });
</script>


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться