Nextrp [CPP] RU + Many GEOs Игра на карте России | NEXTRP

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

javascript file import include

126373 просмотра

24 ответа

15290 Репутация автора

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

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

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

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

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

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

Автор: Adam Источник Размещён: 21.08.2008 09:59

Ответы (24)


8 плюса

15290 Репутация автора

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

  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);
  }
Автор: Adam Размещён: 21.08.2008 10:00

0 плюса

62398 Репутация автора

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

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();
Автор: Darren Kopp Размещён: 21.08.2008 10:01

20 плюса

19083 Репутация автора

Я сделал в основном то же самое, что вы сделали Адам, но с небольшим изменением, чтобы убедиться, что я добавляю тег head, чтобы выполнить работу. Я просто создал функцию включения (код ниже) для обработки как скриптов, так и 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 );
}
Автор: palehorse Размещён: 21.08.2008 10:06

3 плюса

2552 Репутация автора

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

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

function include(url) {
  var s = document.createElement("script");
  s.setAttribute("type", "text/javascript");
  s.setAttribute("src", url);
  document.body.appendChild(s);
}
Автор: Joseph Pecoraro Размещён: 21.08.2008 10:10

2 плюса

22971 Репутация автора

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

Автор: 17 of 26 Размещён: 21.08.2008 11:03

26 плюса

26449 Репутация автора

Недавно я использовал гораздо менее сложную версию с 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>
Автор: travis Размещён: 23.08.2008 03:52

3 плюса

6065 Репутация автора

Я использовал еще одно решение, которое я нашел в сети ... Это находится под 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);
    }
  }   
} 
Автор: Pierre Spring Размещён: 26.08.2008 02:50

77 плюса

7201 Репутация автора

Решение

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

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-запрос и проверить скрипт на глобальном уровне.

Если вы используете Prototype, метод 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);
    }
};
Автор: aemkei Размещён: 28.10.2008 09:02

3 плюса

2275 Репутация автора

Только что узнал о замечательной функции в YUI 3 (на момент написания доступна в предварительной версии). Вы можете легко вставлять зависимости в библиотеки YUI и «внешние» модули (то, что вы ищете) без лишнего кода: 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 .

Автор: Kariem Размещён: 26.03.2009 12:14

2 плюса

79 Репутация автора

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

/*
 * 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 после импорта jquery.js вы просто включите этот файл, чтобы загрузить всю библиотеку и добавить ее в заголовок ...

<script type="text/javascript" src="project.library.js"></script>
Автор: JM Design Размещён: 14.01.2011 09:20

6 плюса

11516 Репутация автора

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

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

Автор: Muhd Размещён: 13.02.2012 08:20

1 плюс

1772 Репутация автора

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

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

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

Автор: 1nfiniti Размещён: 13.02.2012 10:01

14 плюса

9532 Репутация автора

еще один потрясающий ответ

$.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

Автор: Naveed Размещён: 04.04.2012 03:07

55 плюса

8592 Репутация автора

В javascript нет импорта / включения / запроса, но есть два основных способа добиться того, чего вы хотите:

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

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

2 - Добавьте тег сценария с URL-адресом сценария в HTML.

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

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

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

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

Например: 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 для запуска функции обратного вызова при загрузке скрипта. Таким образом, вы можете поместить весь код с помощью удаленной библиотеки в функцию обратного вызова. EG:

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

Затем вы пишете код, который хотите использовать ПОСЛЕ того, как скрипт загружается в лямбда-функцию:

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

Затем вы запускаете все это:

loadScript("my_lovely_script.js", myPrettyCode);

Ладно, я понял. Но писать все эти вещи - боль.

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

$.getScript("my_lovely_script.js", function() {
    alert("Script loaded and executed.");
    // here you can use anything you defined in the loaded script
});
Автор: Dhaval Shah Размещён: 09.02.2013 09:37

1 плюс

999 Репутация автора

Я написал простой модуль, который автоматизирует работу по импорту / включению скриптов модуля в 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
});
Автор: stamat Размещён: 12.04.2013 04:55

3 плюса

613 Репутация автора

Если вы хотите загрузить скрипт 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()); });
Автор: Sielu Размещён: 06.06.2013 06:55

2 плюса

7018 Репутация автора

Делайте это красиво, коротко, просто и легко! :]

// 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]);
    }
}

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

Автор: tfont Размещён: 08.02.2015 01:16

1 плюс

2132 Репутация автора

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

document.write("<script src='https://www.google.com/recaptcha/api.js'></script>");
Автор: adrianTNT Размещён: 04.03.2016 10:08

1 плюс

1957 Репутация автора

Вот простой с обратным вызовом и поддержкой 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');

});
Автор: Jacob Размещён: 08.03.2017 09:40

0 плюса

2630 Репутация автора

Я знаю, что мой ответ немного запоздал на этот вопрос, но вот отличная статья на 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);
});

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

Firefox <3.6, Opera говорит: я понятия не имею, что это за «асинхронная» вещь, но так получилось, что я выполняю сценарии, добавленные через JS, в порядке их добавления.

Safari 5.0 говорит: « Я понимаю« асинхронный », но не понимаю, как установить« ложный »с JS Я выполню ваши сценарии, как только они приземлятся, в любом порядке.

IE <10 говорит: понятия «асинхронный» нет, но есть обходной путь с использованием «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"
])
Автор: asmmahmud Размещён: 03.08.2017 03:42

0 плюса

175 Репутация автора

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

<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>
Автор: James Arnold Размещён: 18.04.2018 01:22

1 плюс

4713 Репутация автора

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

  • вам не нужен jQuery, поэтому вы можете использовать его изначально для загрузки также файла jQuery.js
  • это асинхронный с обратным вызовом
  • он гарантирует, что он загружается только один раз, так как он хранит вложение с записью загруженных URL-адресов, тем самым избегая использования сети
  • В отличие от jQuery $.ajaxили $.getScriptвы можете использовать одноразовые номера, решая, таким образом, проблемы с 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");
Автор: João Pimentel Ferreira Размещён: 26.04.2018 08:54

3 плюса

13399 Репутация автора

Существует новый предложенный стандарт ECMA под названием динамический импорт , недавно включенный в Chrome и Safari.

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

import(moduleSpecifier)
   .then(someModule => someModule.foo()); // executes foo method in someModule
Автор: Alister Размещён: 17.07.2018 09:57

1 плюс

0 Репутация автора

Абсурдная строчка, для тех, кто считает, что загрузка библиотеки 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(...)функцию.

Автор: user993683 Размещён: 17.09.2018 10:10
Вопросы из категории :
32x32