문제

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

스크립트 요소에 사용 가능한 이벤트는 무엇입니까?

도움이 되었습니까?

해결책

동적 스크립트 태그를 작성할 수 있습니다(다음을 사용하여 원기):

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

다른 팁

자바스크립트에는 가져오기/포함/요구가 없지만 원하는 것을 달성하는 두 가지 주요 방법이 있습니다.

1 - AJAX 호출로 로드한 다음 eval을 사용할 수 있습니다.

이는 가장 간단한 방법이지만 Javascript 안전 설정으로 인해 도메인으로 제한되며 eval을 사용하면 버그와 해킹의 문이 열립니다.

2 - HTML에 스크립트 URL이 포함된 스크립트 태그를 추가합니다.

확실히 가장 좋은 방법입니다.외부 서버에서도 스크립트를 로드할 수 있으며, 브라우저 파서를 사용하여 코드를 평가하므로 깔끔합니다.태그는 웹페이지 헤드에 넣을 수도 있고, 본문 하단에 넣을 수도 있습니다.

여기서는 두 가지 솔루션에 대해 논의하고 설명합니다.

이제 당신이 알아야 할 큰 문제가 있습니다.이렇게 하면 코드를 원격으로 로드한다는 의미입니다.최신 웹 브라우저는 성능 향상을 위해 모든 것을 비동기식으로 로드하므로 파일을 로드하고 현재 스크립트를 계속 실행합니다.

이는 이러한 트릭을 직접 사용하면 새로 로드된 코드를 로드하도록 요청한 후 다음 줄에서 사용할 수 없다는 것을 의미합니다. 왜냐하면 코드는 여전히 로드 중이기 때문입니다.

예: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 이벤트를 사용합니다.따라서 원격 라이브러리를 사용하는 모든 코드를 콜백 함수에 넣을 수 있습니다.예:

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

나는 최근에는 훨씬 덜 복잡한 버전 ~와 함께 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, 파이어폭스, 사파리, 오페라.

업데이트: 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>

나는 기본적으로 Adam과 동일한 작업을 수행했지만 작업을 완료하기 위해 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 );
}

또 다른 멋진 답변

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

내가 찾은 몇 가지 예제 코드는 다음과 같습니다.누구든지 더 좋은 방법이 있나요?

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

이미 jQuery를 로드했다면 다음을 사용해야 합니다. $.getScript.

이는 콜백 함수가 내장되어 있고(종속 코드가 실행되기 전에 스크립트가 로드되도록 보장하기 위해) 캐싱을 제어할 수 있다는 점에서 다른 답변에 비해 이점이 있습니다.

누구든지 더 좋은 방법이 있나요?

내 생각에는 본문에 스크립트를 추가하는 것보다 페이지의 마지막 노드에 추가하는 것이 더 쉬울 것 같습니다.이건 어때:

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

나는 인터넷에서 찾은 또 다른 솔루션을 사용했습니다 ...이건 크리에이티브 커먼즈에 속해 있고 함수를 호출하기 전에 소스가 포함되었는지 확인합니다. ...

여기에서 파일을 찾을 수 있습니다: 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);
    }
  }   
} 

방금 훌륭한 기능을 발견했습니다. 유이 3 (작성 당시 미리보기 릴리스에서 사용 가능).너무 많은 코드를 사용하지 않고도 YUI 라이브러리와 "외부" 모듈(원하는 항목)에 종속성을 쉽게 삽입할 수 있습니다. 유이 로더.

또한 외부 모듈이 로드되자마자 호출되는 함수에 관한 두 번째 질문에 답합니다.

예:

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 달력의 예.

당신이 원하는 경우 동조 스크립트를 로딩하려면 HTML HEAD 태그에 직접 스크립트 텍스트를 추가해야 합니다.다음과 같이 추가하면 비동기 짐.외부 파일에서 스크립트 텍스트를 동기적으로 로드하려면 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()); });

우리가 직장에서 사용하는 기술은 AJAX 요청을 사용하여 javascript 파일을 요청한 다음 반환을 eval()하는 것입니다.프로토타입 라이브러리를 사용하는 경우 Ajax.Request 호출에서 이 기능을 지원합니다.

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

사용 - jquery.js를 가져온 후 html/php/etc의 헤드에 이 파일 하나를 포함하면 라이브러리 전체를 로드하여 헤드에 추가할 수 있습니다.

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

멋지고, 짧고, 간단하고, 유지 관리 가능하도록 유지하세요!:]

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

이 코드는 단순히 다음과 같은 간단한 기능적 예입니다. ~할 수 있었다 모든 (또는 특정) 플랫폼에서 완전한 지원을 위해서는 추가 기능이 필요합니다.

새로 제안된 ECMA 표준이 있습니다. 동적 가져오기, 최근 Chrome 및 Safari에 통합되었습니다.

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

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

이 목적을 위해 특별히 설계된 스크립트가 있습니다.

yepnope.js Modernizr에 내장되어 있으며 lab.js 더 최적화되었지만 사용자 친화적인 버전은 아닙니다.

jquery나 프로토타입과 같은 대규모 라이브러리를 통해 이 작업을 수행하는 것을 권장하지 않습니다. 스크립트 로더의 주요 이점 중 하나는 스크립트를 조기에 로드할 수 있다는 것입니다. jquery 및 모든 dom 요소가 로드되기 전에 기다릴 필요가 없습니다. 스크립트를 동적으로 로드할지 확인하기 위해 검사를 실행합니다.

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

이 모든 샘플에서 길을 잃었지만 오늘은 기본 .js에서 외부 .js를 로드해야 했고 다음과 같이 했습니다.

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

여기 콜백과 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');

});

다음은 JS 파일을 로드하는 함수에 대한 간단한 예입니다.관련 사항:

  • jQuery가 필요하지 않으므로 처음에 이것을 사용하여 jQuery.js 파일도 로드할 수 있습니다.
  • 콜백과 비동기입니다
  • 로드된 URL 기록이 포함된 인클로저를 유지하여 네트워크 사용을 방지하므로 한 번만 로드되도록 보장합니다.
  • jQuery와 반대 $.ajax 또는 $.getScript nonce를 사용하여 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");

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(...) 기능.

jscript, 프로토타입, 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();

이 질문에 대한 답변이 다소 늦었다는 것을 알고 있지만, 여기에 훌륭한 기사가 있습니다. www.html5rocks.com - 스크립트 로딩의 어두운 바다에 대해 자세히 알아보세요. .

해당 기사에서는 브라우저 지원과 관련하여 콘텐츠 렌더링을 차단하지 않고 JavaScript 파일을 동적으로 로드하는 가장 좋은 방법은 다음과 같은 방법이라고 결론지었습니다.

이름이 4개인 스크립트가 있다고 생각하면 script1.js, script2.js, script3.js, script4.js 그럼 당신은 그것을 할 수 있습니다 비동기 적용 = 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는 다음과 같이 말합니다. 나는 이 "비동기"가 무엇인지 전혀 모르지만 JS를 통해 추가된 스크립트를 추가된 순서대로 실행합니다.

사파리 5.0은 다음과 같이 말합니다. "비동기"는 이해하지만 JS에서 "false"로 설정하는 것은 이해하지 못합니다.순서에 관계없이 스크립트가 착륙하자마자 실행하겠습니다.

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"
])

이 같은...

<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>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top