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
});
위의 코드에서 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 % 신뢰할 수 없습니다!?를 사용하여 찾은 것과 동일합니다.
원하는 경우 오류 / 실패 처리 동작을 추가 할 수 있습니다.
답변
$.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
});
이것이 약속을 사용하고 최소한의 오버 헤드를 갖는 방법입니다.