IT박스

jQuery $ .getScript () 메소드를 사용하여 여러 JS 파일을 포함하는 방법

itboxs 2020. 7. 16. 19:49
반응형

jQuery $ .getScript () 메소드를 사용하여 여러 JS 파일을 포함하는 방법


js 파일에 자바 스크립트 파일을 동적으로 포함하려고합니다. 나는 그것에 대해 약간의 연구를했고 jQuery $ .getScript () 메소드가 원하는 방법이라는 것을 알았습니다.

// jQuery
$.getScript('/path/to/imported/script.js', function()
{
    // script is now loaded and executed.
    // put your dependent JS here.
    // what if the JS code is dependent on multiple JS files? 
});

그러나이 방법이 한 번에 여러 스크립트를로드 할 수 있는지 궁금합니다. 내가 묻는 이유는 때때로 내 자바 스크립트 파일이 둘 이상의 js 파일에 의존하기 때문입니다.

미리 감사드립니다.


정답은

getScript()다음과 같은 약속을 사용 하고 모든 스크립트가로드 될 때까지 기다릴 수 있습니다 .

$.when(
    $.getScript( "/mypath/myscript1.js" ),
    $.getScript( "/mypath/myscript2.js" ),
    $.getScript( "/mypath/myscript3.js" ),
    $.Deferred(function( deferred ){
        $( deferred.resolve );
    })
).done(function(){

    //place your code here, the scripts are all loaded

});

깡깡이

ANOTHER 뿐인

위의 코드에서 Deferred를 추가하고 내부에서 해결하는 것은 $()jQuery 호출 내에 다른 함수를 배치 $(func)하는 것과 같습니다.

$(function() { func(); });

즉, DOM이 준비 될 때까지 대기하므로 위의 예 $.when에서는 모든 스크립트가로드 되고$.Deferred DOM 준비 콜백에서 해결 되는 호출로 인해 DOM이 준비 될 때까지 대기 합니다.


보다 일반적인 사용을 위해 편리한 기능

모든 스크립트 배열을 허용하는 유틸리티 함수는 다음과 같이 만들 수 있습니다.

$.getMultiScripts = function(arr, path) {
    var _arr = $.map(arr, function(scr) {
        return $.getScript( (path||"") + scr );
    });

    _arr.push($.Deferred(function( deferred ){
        $( deferred.resolve );
    }));

    return $.when.apply($, _arr);
}

이것처럼 사용할 수 있습니다

var script_arr = [
    'myscript1.js', 
    'myscript2.js', 
    'myscript3.js'
];

$.getMultiScripts(script_arr, '/mypath/').done(function() {
    // all scripts loaded
});

여기서 경로는 모든 스크립트 앞에 추가되며 선택 사항이기도합니다. 즉, 배열에 전체 URL이 포함 된 경우이 작업을 수행 할 수 있으며 경로를 모두 생략 할 수 있습니다.

$.getMultiScripts(script_arr).done(function() { ...

인수, 오류 등

또한 done콜백에는 전달 된 스크립트와 일치하는 여러 인수가 포함되며 각 인수는 응답을 포함하는 배열을 나타냅니다.

$.getMultiScripts(script_arr).done(function(response1, response2, response3) { ...

각 배열은 다음과 같은 것을 포함합니다 [content_of_file_loaded, status, xhr_object]. 우리는 일반적으로 스크립트가 자동으로로드되기 때문에 일반적으로 이러한 인수에 액세스 할 필요가 없으며 대부분의 경우 done콜백은 모든 스크립트가로드되었다는 사실을 알게 된 것이므로 완성도를 위해 추가하고 있습니다. 드문 경우지만로드 된 파일의 실제 텍스트에 액세스해야하거나 각 XHR 개체 또는 이와 유사한 항목에 액세스해야하는 경우가 있습니다.

또한 스크립트가로드되지 않으면 실패 핸들러가 호출되고 후속 스크립트가로드되지 않습니다.

$.getMultiScripts(script_arr).done(function() {
     // all done
}).fail(function(error) {
     // one or more scripts failed to load
}).always(function() {
     // always called, both on success and error
});

여러 스크립트를 병렬로로드하는 간단한 기능을 구현했습니다.

함수

function getScripts(scripts, callback) {
    var progress = 0;
    scripts.forEach(function(script) { 
        $.getScript(script, function () {
            if (++progress == scripts.length) callback();
        }); 
    });
}

용법

getScripts(["script1.js", "script2.js"], function () {
    // do something...
});

이전 스크립트의 콜백에 다음 필수 스크립트를로드하십시오.

$.getScript('scripta.js', function()
{
   $.getScript('scriptb.js', function()
   {
       // run script that depends on scripta.js and scriptb.js
   });
});

때로는 특정 순서로 스크립트를로드해야합니다. 예를 들어 jQuery UI보다 먼저 jQuery를로드해야합니다. 이 페이지의 대부분의 예제는 스크립트를 병렬로 (비동기 적으로)로드하므로 실행 순서가 보장되지 않습니다. 순서가 없으면 둘 다 성공적으로로드되었지만 순서가 잘못된 경우 y에 의존하는 스크립트 x가 중단 될 수 있습니다.

종속 스크립트의 순차적 로딩 + 선택적 병렬 로딩 + 지연된 객체 를 허용하는 하이브리드 접근법을 제안 합니다 .

/*
 * loads scripts one-by-one using recursion
 * returns jQuery.Deferred
 */
function loadScripts(scripts) {
  var deferred = jQuery.Deferred();

  function loadScript(i) {
    if (i < scripts.length) {
      jQuery.ajax({
        url: scripts[i],
        dataType: "script",
        cache: true,
        success: function() {
          loadScript(i + 1);
        }
      });
    } else {
      deferred.resolve();
    }
  }
  loadScript(0);

  return deferred;
}

/*
 * example using serial and parallel download together
 */

// queue #1 - jquery ui and jquery ui i18n files
var d1 = loadScripts([
  "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js",
  "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/i18n/jquery-ui-i18n.min.js"
]).done(function() {
  jQuery("#datepicker1").datepicker(jQuery.datepicker.regional.fr);
});

// queue #2 - jquery cycle2 plugin and tile effect plugin
var d2 = loadScripts([
  "https://cdn.rawgit.com/malsup/cycle2/2.1.6/build/jquery.cycle2.min.js",
  "https://cdn.rawgit.com/malsup/cycle2/2.1.6/build/plugin/jquery.cycle2.tile.min.js"

]).done(function() {
  jQuery("#slideshow1").cycle({
    fx: "tileBlind",
    log: false
  });
});

// trigger a callback when all queues are complete
jQuery.when(d1, d2).done(function() {
  console.log("All scripts loaded");
});
@import url("https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/blitzer/jquery-ui.min.css");

#slideshow1 {
  position: relative;
  z-index: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<p><input id="datepicker1"></p>

<div id="slideshow1">
  <img src="https://dummyimage.com/300x100/FC0/000">
  <img src="https://dummyimage.com/300x100/0CF/000">
  <img src="https://dummyimage.com/300x100/CF0/000">
</div>

두 대기열의 스크립트는 동시에 다운로드되지만 각 대기열의 스크립트는 순서대로 다운로드되어 순서대로 실행됩니다. 폭포 형 차트 :

스크립트의 폭포 형 차트


사용 yepnope.js 또는 모더 나이저 (이 같이 yepnope.js을 포함한다 Modernizr.load).

최신 정보

후속 조치를 위해 현재 yepnope를 사용하고있는 것과 동등하게 여러 스크립트에 대한 종속성을 보여줍니다.

yepnope({
  load: ['script1.js', 'script2.js', 'script3.js'],
  complete: function () {
      // all the scripts have loaded, do whatever you want here
  }
});

크로스 도메인이 완벽하게 작동하는 Ajax에 의해 성공적으로로드 된 후 실제로 실행되지 않는 스크립트의 동일한 도메인 핫로드로 하나 이상의 문제를 발생시키는 다중 스크립트로드와 관련된 여러 문제가 발생했습니다! :(

원래 질문에 선택된 답변이 안정적으로 작동하지 않습니다.

여러 번 반복 한 후에는 getScript에 대한 최종 답변이며 스크립트 당로드 된 콜백 옵션 및 완료시 전체 콜백과 함께 특정 엄격한 순서로 여러 스크립트를 비동기 적으로로드합니다 .jQuery 2.1 이상 및 최신 버전의 Chrome에서 테스트되었습니다. 버려진 Internet Explorer.

내 테스트 사례는 THREE.JS webGL 렌더 파일을로드 한 다음 onComplete에 대한 익명 함수 호출에 전달 된 간격 검사를 사용하여 THREE 전역을 사용할 수있을 때 렌더 스크립트를 시작했습니다.

프로토 타입 함수 (getScripts)

function getScripts( scripts, onScript, onComplete )
{
    this.async = true;
    this.cache = false;
    this.data = null;
    this.complete = function () { $.scriptHandler.loaded(); };
    this.scripts = scripts;
    this.onScript = onScript;
    this.onComplete = onComplete;
    this.total = scripts.length;
    this.progress = 0;
};

getScripts.prototype.fetch = function() {
    $.scriptHandler = this;
    var src = this.scripts[ this.progress ];
    console.log('%cFetching %s','color:#ffbc2e;', src);

    $.ajax({
        crossDomain:true,
        async:this.async,
        cache:this.cache,
        type:'GET',
        url: src,
        data:this.data,
        statusCode: {
            200: this.complete
        },
        dataType:'script'
    });
};

getScripts.prototype.loaded = function () {
    this.progress++;
    if( this.progress >= this.total ) {
        if(this.onComplete) this.onComplete();
    } else {
        this.fetch();
    };
    if(this.onScript) this.onScript();
};

사용하는 방법

var scripts = new getScripts(
    ['script1.js','script2.js','script.js'],
    function() {
        /* Optional - Executed each time a script has loaded (Use for Progress updates?) */
    },
    function () {
        /* Optional - Executed when the entire list of scripts has been loaded */
    }
);
scripts.fetch();

이 기능은 Deferred (Deprecated now?), When, Success & Complete in Trials를 100 % 신뢰할 수 없습니다!?를 사용하여 찾은 그대로입니다. 따라서이 기능과 statusCode 사용을 예로들 수 있습니다.

원하는 경우 오류 / 실패 처리 동작을 추가 할 수 있습니다.


$.when다음 함수를 시도하여 -method를 사용할 수 있습니다.

function loadScripts(scripts) {
  scripts.forEach(function (item, i) {
    item = $.getScript(item);
  });
  return $.when.apply($, scripts);
}

이 기능은 다음과 같이 사용됩니다 :

loadScripts(['path/to/script-a.js', 'path/to/script-b.js']).done(function (respA, respB) {
    // both scripts are loaded; do something funny
});

이것이 약속을 사용하고 최소한의 오버 헤드를 갖는 방법입니다.


좋은 대답입니다.

답변을보다 일반적인 것으로 만드는 방법을 알아내는 데 약간의 시간이 걸렸습니다 (코드 정의 스크립트 배열을로드 할 수 있도록). 모든 스크립트가로드되고 실행될 때 콜백이 호출됩니다. 내 해결책은 다음과 같습니다.

    function loadMultipleScripts(scripts, callback){
        var array = [];

        scripts.forEach(function(script){
            array.push($.getScript( script ))
        });

        array.push($.Deferred(function( deferred ){
                    $( deferred.resolve );
                }));

        $.when.apply($, array).done(function(){
                if (callback){
                    callback();
                }
            });
    }

당신이 찾고있는 것은 AMD 호환 로더입니다 (예 : require.js).

http://requirejs.org/

http://requirejs.org/docs/whyamd.html

당신이 그것을 보면 좋은 오픈 소스 것들이 많이 있습니다. 기본적으로이를 통해 코드 모듈을 정의 할 수 있으며 다른 코드 모듈에 종속 된 경우 해당 모듈의 다운로드가 끝날 때까지 기다렸다가 실행을 계속합니다. 이 방법으로 10 개의 모듈을 비동기식으로로드 할 수 있으며 다른 모듈 중 일부를 실행하더라도 문제가 발생하지 않습니다.


이 기능은 종속 파일이 완전히로드 된 후 파일이로드되도록합니다. 다른 파일에 대한 종속성을 염두에두고 파일을 순서대로 제공하면됩니다.

function loadFiles(files, fn) {
    if (!files.length) {
        files = [];
    }
    var head = document.head || document.getElementsByTagName('head')[0];

    function loadFile(index) {
        if (files.length > index) {
            var fileref = document.createElement('script');
            fileref.setAttribute("type", "text/javascript");
            fileref.setAttribute("src", files[index]);
            head.appendChild(fileref);
            index = index + 1;
            // Used to call a callback function
            fileref.onload = function () {
                loadFile(index);
            }
        } else if(fn){
            fn();
        }
    }
    loadFile(0);
}

이것은 나를 위해 작동합니다 :

function getScripts(scripts) {
    var prArr = [];
    scripts.forEach(function(script) { 
        (function(script){
            prArr .push(new Promise(function(resolve){
                $.getScript(script, function () {
                    resolve();
                });
            }));
        })(script);
    });
    return Promise.all(prArr, function(){
        return true;
    });
}

그리고 그것을 사용하십시오 :

var jsarr = ['script1.js','script2.js'];
getScripts(jsarr).then(function(){
...
});

다음은 Maciej Sawicki를 사용 Promise하고 콜백으로 구현 한 답변입니다 .

function loadScripts(urls, path) {
    return new Promise(function(resolve) {
        urls.forEach(function(src, i) {

            let script = document.createElement('script');        
            script.type = 'text/javascript';
            script.src = (path || "") + src;
            script.async = false;

            // If last script, bind the callback event to resolve
            if(i == urls.length-1) {                    
                // Multiple binding for browser compatibility
                script.onreadystatechange = resolve;
                script.onload = resolve;
            }

            // Fire the loading
            document.body.appendChild(script);
        });
    });
}

사용하다:

let JSDependencies = ["jquery.js",
                      "LibraryNeedingJquery.js",
                      "ParametersNeedingLibrary.js"];

loadScripts(JSDependencies,'JavaScript/').then(taskNeedingParameters);

모든 Javascript 파일은 가능한 빨리 다운로드되어 주어진 순서대로 실행됩니다. 그런 다음 taskNeedingParameters호출됩니다.


Andrew Marc Newton의 종합 답변의 짧은 버전. 이것은 정의되지 않은 UI 동작을 피하기 위해 수행해야하는 상태 코드의 성공 여부를 확인하지 않습니다.

이것은 jQuery를 보장 할 수 있지만 다른 포함을 보장 할 수없는 성가신 시스템을위한 것이므로 강제로 외부 스크립트에 빠지지 않을 정도로 짧은 기술을 원했습니다. (인덱스 0을 첫 번째 "재귀"호출에 전달하면 더 짧게 만들 수 있지만 스타일 습관이 강 해져서 설탕을 첨가하게되었습니다.

또한 종속성 목록을 모듈 이름에 할당하고 있으므로이 블록은 "module1"이 필요한 모든 곳에 포함될 수 있으며 스크립트 및 종속 초기화는 한 번만 포함 / 실행됩니다 ( index콜백에 로그인 하여 단일 순서를 볼 수 있음) 실행중인 AJAX 요청 세트)

if(typeof(__loaders) == 'undefined') __loaders = {};

if(typeof(__loaders.module1) == 'undefined')
{
    __loaders.module1 = false;

    var dependencies = [];

    dependencies.push('/scripts/loadmefirst.js');
    dependencies.push('/scripts/loadmenext.js');
    dependencies.push('/scripts/loadmelast.js');

    var getScriptChain  = function(chain, index)        
    {
        if(typeof(index) == 'undefined')
            index = 0;

        $.getScript(chain[index], 
            function()
            {
                if(index == chain.length - 1)
                {
                    __loaders.module1 = true;

                    /* !!!
                        Do your initialization of dependent stuff here 
                    !!! */
                }
                else 
                    getScriptChain(chain, index + 1);
            }
        );
    };

    getScriptChain(dependencies);       
}

jQuery의 getScript 메소드를 확장하는 플러그인이 있습니다. 비동기식 및 동기식 로딩을 허용하고 jQuery의 캐싱 메커니즘을 사용합니다. 전체 공개, 나는 이것을 썼다. 더 나은 방법을 찾으면 부담없이 참여하십시오.

https://github.com/hudsonfoo/jquery-getscripts


n 개의 스크립트를 하나씩 로드합니다 (예 : 두 번째 파일에 첫 번째 스크립트가 필요한 경우에 유용함).

(function self(a,cb,i){
    i = i || 0; 
    cb = cb || function(){};    
    if(i==a.length)return cb();
    $.getScript(a[i++],self.bind(0,a,cb,i));                    
})(['list','of','script','urls'],function(){console.log('done')});

위의 @adeneo의 답변을 기반으로 : CSS 및 js 파일로드를 결합

개선을위한 제안?

// Usage
//$.getMultiResources(['script-1.js','style-1.css'], 'assets/somePath/')
//  .done(function () {})
//  .fail(function (error) {})
//  .always(function () {});

(function ($) {
  $.getMultiResources = function (arr, pathOptional, cache) {
    cache = (typeof cache === 'undefined') ? true : cache;
    var _arr = $.map(arr, function (src) {
      var srcpath = (pathOptional || '') + src;
      if (/.css$/i.test(srcpath)) {
        return $.ajax({
          type: 'GET',
          url: srcpath,
          dataType: 'text',
          cache: cache,
          success: function () {
            $('<link>', {
              rel: 'stylesheet',
              type: 'text/css',
              'href': srcpath
            }).appendTo('head');
          }
        });

      } else {
        return $.ajax({
          type: 'GET',
          url: srcpath,
          dataType: 'script',
          cache: cache
        });
      }
    });
    //
    _arr.push($.Deferred(function (deferred) {
      $(deferred.resolve);
    }));
    //
    return $.when.apply($, _arr);
  };
})(jQuery);

async = false로 스크립트 추가

여기에 다르지만 매우 간단한 접근 방식이 있습니다. 여러 스크립트를로드하려면 본문에 간단히 추가하면됩니다.

  • 브라우저가 페이지로드를 최적화하는 방식이므로 비동기 적으로로드합니다.
  • 브라우저가 HTML 태그를 구문 분석하는 방식이므로 스크립트를 순서대로 실행합니다.
  • 스크립트가 순서대로 실행되므로 콜백이 필요하지 않습니다. 다른 스크립트를 추가하기 만하면 다른 스크립트 후에 실행됩니다.

자세한 정보는 여기 : https://www.html5rocks.com/en/tutorials/speed/script-loading/

var scriptsToLoad = [
   "script1.js", 
   "script2.js",
   "script3.js",
]; 

scriptsToLoad.forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.body.appendChild(script);
});

재귀를 사용하여 시도해 볼 수 있습니다. 그러면 전체 목록 다운로드가 완료 될 때까지 하나씩 동기화되어 다운로드됩니다.

var queue = ['url/links/go/here'];

ProcessScripts(function() { // All done do what ever you want

}, 0);

function ProcessScripts(cb, index) {
    getScript(queue[index], function() {
        index++;
        if (index === queue.length) { // Reached the end
            cb();
        } else {
            return ProcessScripts(cb, index);
        }
    });
}

function getScript(script, callback) {
    $.getScript(script, function() {
        callback();
    });
}

참고 URL : https://stackoverflow.com/questions/11803215/how-to-include-multiple-js-files-using-jquery-getscript-method

반응형