Javascript 如何使用 jQuery $.getScript() 方法包含多个 js 文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11803215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to include multiple js files using jQuery $.getScript() method
提问by sozhen
I am trying to dynamically include javascript files into my js file. I did some research about it and find jQuery $.getScript() method would be a desired way to go.
我正在尝试将 javascript 文件动态包含到我的 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?
});
But I am wondering whether this method can load multiple scripts at one time? Why I am asking this is because sometimes my javascript file is depending on more than one js files.
但是我想知道这种方法是否可以一次加载多个脚本?为什么我问这个是因为有时我的 javascript 文件依赖于多个 js 文件。
Thank you in advance.
先感谢您。
回答by adeneo
The answer is
答案是
You can use promises with getScript()
and wait until all the scripts are loaded, something like:
您可以使用 promisegetScript()
并等待所有脚本加载完毕,例如:
$.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
});
In the above code, adding a Deferred and resolving it inside $()
is like placing any other function inside a jQuery call, like $(func)
, it's the same as
在上面的代码中,添加一个 Deferred 并在里面解析它$()
就像在 jQuery 调用中放置任何其他函数一样$(func)
,就像,它与
$(function() { func(); });
i.e. it waits for the DOM to be ready, so in the above example $.when
waits for all the scripts to be loaded andfor the DOM to be ready because of the $.Deferred
call which resolves in the DOM ready callback.
即它等待 DOM 准备好,因此在上面的示例中,$.when
等待所有脚本加载并等待DOM 准备好,因为$.Deferred
在 DOM 准备好回调中解析的调用。
For more generic use, a handy function
对于更通用的用途,一个方便的功能
A utility function that accepts any array of scripts could be created like this :
可以像这样创建一个接受任何脚本数组的实用程序函数:
$.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);
}
which can be used like this
可以这样使用
var script_arr = [
'myscript1.js',
'myscript2.js',
'myscript3.js'
];
$.getMultiScripts(script_arr, '/mypath/').done(function() {
// all scripts loaded
});
where the path will be prepended to all scripts, and is also optional, meaning that if the array contain the full URL's one could also do this, and leave out the path all together
路径将被添加到所有脚本的前面,并且也是可选的,这意味着如果数组包含完整的 URL,也可以这样做,并且将路径一起省略
$.getMultiScripts(script_arr).done(function() { ...
Arguments, errors etc.
参数、错误等。
As an aside, note that the done
callback will contain a number of arguments matching the passed in scripts, each argument representing an array containing the response
顺便说done
一句,请注意回调将包含许多与传入脚本匹配的参数,每个参数代表一个包含响应的数组
$.getMultiScripts(script_arr).done(function(response1, response2, response3) { ...
where each array will contain something like [content_of_file_loaded, status, xhr_object]
.
We generally don't need to access those arguments as the scripts will be loaded automatically anyway, and most of the time the done
callback is all we're really after to know that all scripts have been loaded, I'm just adding it for completeness, and for the rare occasions when the actual text from the loaded file needs to be accessed, or when one needs access to each XHR object or something similar.
其中每个数组将包含类似[content_of_file_loaded, status, xhr_object]
. 我们通常不需要访问这些参数,因为无论如何脚本都会自动加载,而且大多数时候done
回调是我们真正想要知道所有脚本都已加载的全部内容,我只是为了完整性而添加它,以及在极少数情况下需要访问加载文件中的实际文本,或者需要访问每个 XHR 对象或类似内容时。
Also, if any of the scripts fail to load, the fail handler will be called, and subsequent scripts will not be loaded
此外,如果任何脚本加载失败,将调用失败处理程序,并且不会加载后续脚本
$.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
});
回答by Andrei
I implemented a simple function to load multiple scripts in parallel:
我实现了一个简单的函数来并行加载多个脚本:
Function
功能
function getScripts(scripts, callback) {
var progress = 0;
scripts.forEach(function(script) {
$.getScript(script, function () {
if (++progress == scripts.length) callback();
});
});
}
Usage
用法
getScripts(["script1.js", "script2.js"], function () {
// do something...
});
回答by Frankey
Load the following up needed script in the callback of the previous one like:
在前一个的回调中加载后续所需的脚本,例如:
$.getScript('scripta.js', function()
{
$.getScript('scriptb.js', function()
{
// run script that depends on scripta.js and scriptb.js
});
});
回答by Salman A
Sometimes it is necessary to load scripts in a specific order. For example jQuery must be loaded before jQuery UI. Most examples on this page load scripts in parallel (asynchronously) which means order of execution is not guaranteed. Without ordering, script y
that depends on x
could break if both are successfully loaded but in wrong order.
有时需要按特定顺序加载脚本。例如 jQuery 必须在 jQuery UI 之前加载。此页面上的大多数示例并行(异步)加载脚本,这意味着无法保证执行顺序。如果没有排序,如果两者都成功加载但顺序错误y
,则依赖的脚本x
可能会中断。
I propose a hybrid approach which allows sequential loading of dependent scripts + optional parallel loading + deferred objects:
我提出了一种混合方法,它允许顺序加载依赖脚本 + 可选的并行加载 +延迟对象:
/*
* 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>
The scripts in both queues will download in parallel, however, the scripts in each queue will download in sequence, ensuring ordered execution. Waterfall chart:
两个队列中的脚本将并行下载,但每个队列中的脚本将依次下载,确保有序执行。瀑布图:
回答by Marc
I ran into a number of issues with multi script loading inculding one issue with (at least in Chrome) same domain hot loading of scripts not actually running after being successfully loaded by Ajax where as Cross Domain works perfectly fine! :(
我遇到了多脚本加载的许多问题,其中一个问题是(至少在 Chrome 中)相同域的脚本热加载在被 Ajax 成功加载后实际上没有运行,而跨域工作得很好!:(
The selected answer to original question does not work reliably.
原始问题的选定答案不能可靠地工作。
After many many iterations here is my final answer to getScript(s) and loading asynchronously multiple scripts in a specific strict order with per script loaded callback option and overall callback on completion, Tested in jQuery 2.1+ and modern versions of Chrome, Firefox plus the forsaken Internet Explorer.
经过多次迭代,这里是我对 getScript(s) 和以特定严格顺序异步加载多个脚本的最终答案,每个脚本加载回调选项和完成时的整体回调,在 jQuery 2.1+ 和现代版本的 Chrome、Firefox 和被抛弃的 Internet Explorer。
My test case was loading files for a THREE.JS webGL render then starting the render script when THREE global became available using an interval check passed to an anonymous function call to onComplete.
我的测试用例是为一个 THREE.JS webGL 渲染加载文件,然后当三个全局可用时启动渲染脚本,使用间隔检查传递给对 onComplete 的匿名函数调用。
The Prototype function ( getScripts )
原型函数 ( 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();
};
How to use
如何使用
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();
The function is as it is for I found using Deferred ( Deprecated now? ), When, Success & Complete in my trials to NOT be 100% reliable!?, Hence this function and use of statusCode for example.
该功能是因为我发现使用延迟(现在已弃用?),在我的试验中,何时、成功和完成不是 100% 可靠的!?,因此此功能和使用 statusCode 为例。
You may want to add in error/fail handling behaviour if you wish.
如果您愿意,您可能希望添加错误/失败处理行为。
回答by Chris Pratt
Use yepnope.jsor Modernizr(which includes yepnope.js as Modernizr.load
).
使用yepnope.js或Modernizr(包括 yepnope.js as Modernizr.load
)。
UPDATE
更新
Just to follow up, here's a good equivalent of what you currently have using yepnope, showing dependencies on multiple scripts:
只是为了跟进,这是您目前使用 yepnope 的一个很好的等价物,显示了对多个脚本的依赖:
yepnope({
load: ['script1.js', 'script2.js', 'script3.js'],
complete: function () {
// all the scripts have loaded, do whatever you want here
}
});
回答by Emanuel Kluge
You could make use of the $.when
-method by trying the following function:
您可以$.when
通过尝试以下函数来使用-method:
function loadScripts(scripts) {
scripts.forEach(function (item, i) {
item = $.getScript(item);
});
return $.when.apply($, scripts);
}
This function would be used like this:
这个函数会像这样使用:
loadScripts(['path/to/script-a.js', 'path/to/script-b.js']).done(function (respA, respB) {
// both scripts are loaded; do something funny
});
That's the way to use Promises and have a minimum of overhead.
这就是使用 Promises 并且开销最小的方式。
回答by RoccoB
Great answer, adeneo.
很好的答案,adeneo。
It took me a little while to figure out how to make your answer more generic (so that I could load an array of code-defined scripts). Callback gets called when all scripts have loaded and executed. Here is my solution:
我花了一些时间才弄清楚如何使您的答案更通用(以便我可以加载一组代码定义的脚本)。当所有脚本加载并执行时,回调被调用。这是我的解决方案:
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();
}
});
}
回答by Maciej Sawicki
Append scripts with async=false
使用 async=false 附加脚本
Here's a different, but super simple approach. To load multiple scripts you can simply append them to body.
这是一种不同但超级简单的方法。要加载多个脚本,您可以简单地将它们附加到正文。
- Loads them asynchronously, because that's how browsers optimize the page loading
- Executes scripts in order, because that's how browsers parse the HTML tags
- No need for callback, because scripts are executed in order. Simply add another script, and it will be executed after the other scripts
- 异步加载它们,因为这是浏览器优化页面加载的方式
- 按顺序执行脚本,因为这是浏览器解析 HTML 标签的方式
- 不需要回调,因为脚本是按顺序执行的。只需添加另一个脚本,它会在其他脚本之后执行
More info here: https://www.html5rocks.com/en/tutorials/speed/script-loading/
更多信息在这里: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);
});
回答by H4dr1en
Here is answer using Maciej Sawicki's one and implementing Promise
as callback:
这是使用 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);
});
});
}
Use:
用:
let JSDependencies = ["jquery.js",
"LibraryNeedingJquery.js",
"ParametersNeedingLibrary.js"];
loadScripts(JSDependencies,'JavaScript/').then(taskNeedingParameters);
All Javascript files are downloaded as soon as possible and executed in the given order. Then taskNeedingParameters
is called.
尽快下载所有 Javascript 文件并按给定顺序执行。然后taskNeedingParameters
被调用。