异步加载脚本 [英] load scripts asynchronously
问题描述
我正在使用 JQuery 中的几个插件、自定义小部件和其他一些库.结果我有几个 .js 和 .css 文件.我需要为我的网站创建一个加载器,因为加载需要一些时间.如果我可以在导入所有内容之前显示加载程序,那就太好了:
I am using several plugins, custom widgets and some other libraries from JQuery. as a result I have several .js and .css files. I need to create a loader for my site because it takes some time to load. it will be nice if I can display the loader before importing all the:
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
...
....
etc
我找到了几个教程,可以让我异步导入 JavaScript 库.例如,我可以执行以下操作:
I have found several tutorials that enable me to import a JavaScript library asynchronously. for example I can do something like:
(function () {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'js/jquery-ui-1.8.16.custom.min.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
})();
出于某种原因,当我对所有文件执行相同操作时,页面不起作用.我已经尝试了很长时间试图找到问题所在,但我就是找不到它.首先我认为这可能是因为某些 javascript 函数依赖于其他函数.但是当一个完成时我使用超时功能以正确的顺序加载它们我继续下一个并且页面仍然表现得很奇怪.例如,我无法点击链接等...动画仍然有效...
for some reason when I do the same thing for all my files the pages does not work. I have been trying for so long to try to find where the problem is but I just cannot find it. First I thought that it was probably because some javascript functions depended on the others. but I loaded them in the right order using the time out function when one completed I proceeded with the next and the page still behaves weird. for example I am not able to click on links etc... animations still work though..
这就是我一直在想的……我相信浏览器有一个缓存,这就是为什么第一次加载页面需要很长时间,而下一次加载很快.所以我想做的是用异步加载所有这些文件的页面替换我的 index.html 页面.当 ajax 完成加载所有这些文件时,重定向到我打算使用的页面.使用该页面时,加载时间应该不会太长,因为这些文件应该已经包含在浏览器的缓存中.在我的索引页(.js 和 .css 文件被异步加载的页面)上,我不在乎出现错误.我将只显示一个加载程序并在完成后重定向页面...
Here is what I have been thinking... I believe browsers have a cache that's why it takes a long time to load the page for the first time and the next time it is quick. so what I am thinking of doing is replacing my index.html page with a page that loads all this files asynchronously. when ajax is done loading all those files redirect to the page that I plan on using. when using that page it should not take long to load since the files should alredy be included on the cache of the browser. on my index page (page where .js and .css file get loaded asynchronously) I don't care of getting errors. I will just be displaying a loader and redirecting the page when done...
这个想法是一个不错的选择吗?还是应该继续尝试实现异步方法?
Is this idea a good alternative? or should I keep trying on implementing the asynchronously methods?
我异步加载所有内容的方式如下:
the way I load everything async is like:
importScripts();
function importScripts()
{
//import: jquery-ui-1.8.16.custom.min.js
getContent("js/jquery-1.6.2.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
//s.async = true;
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext1,1);
});
//import: jquery-ui-1.8.16.custom.min.js
function insertNext1()
{
getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext2,1);
});
}
//import: jquery-ui-1.8.16.custom.css
function insertNext2()
{
getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext3,1);
});
}
//import: main.css
function insertNext3()
{
getContent("css/main.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext4,1);
});
}
//import: jquery.imgpreload.min.js
function insertNext4()
{
getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext5,1);
});
}
//import: marquee.js
function insertNext5()
{
getContent("js/marquee.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext6,1);
});
}
//import: marquee.css
function insertNext6()
{
getContent("css/marquee.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext,1);
});
}
function insertNext()
{
setTimeout(pageReadyMan,10);
}
}
// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
// attempt to create the XMLHttpRequest and make the request
try
{
var asyncRequest; // variable to hold XMLHttpRequest object
asyncRequest = new XMLHttpRequest(); // create request object
// register event handler
asyncRequest.onreadystatechange = function(){
stateChange(asyncRequest, callBackFunction);
}
asyncRequest.open( 'GET', url, true ); // prepare the request
asyncRequest.send( null ); // send the request
} // end try
catch ( exception )
{
alert( 'Request failed.' );
} // end catch
} // end function getContent
// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
{
callBackFunction(asyncRequest.responseText);
} // end if
} // end function stateChange
奇怪的部分是所有样式的工作加上所有 javascript 功能.页面由于某种原因被冻结...
and the weird part is that all the style's work plus all the javascript functions. the page is frozen for some reason though...
推荐答案
异步加载的几个解决方案:
A couple solutions for async loading:
//this function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
var s,
r,
t;
r = false;
s = document.createElement('script');
s.type = 'text/javascript';
s.src = src;
s.onload = s.onreadystatechange = function() {
//console.log( this.readyState ); //uncomment this line to see which ready states are called.
if ( !r && (!this.readyState || this.readyState == 'complete') )
{
r = true;
callback();
}
};
t = document.getElementsByTagName('script')[0];
t.parentNode.insertBefore(s, t);
}
如果页面上已经有 jQuery,只需使用:
If you've already got jQuery on the page, just use:
$.getScript(url, successCallback)
*
此外,您的脚本可能在文档加载完成之前被加载/执行,这意味着您需要等待 document.ready
事件才能绑定到元素.
Additionally, it's possible that your scripts are being loaded/executed before the document is done loading, meaning that you'd need to wait for document.ready
before events can be bound to the elements.
如果不查看代码,就无法具体说明您的问题是什么.
It's not possible to tell specifically what your issue is without seeing the code.
最简单的解决方案是将所有脚本内嵌在页面底部,这样它们在执行时就不会阻止加载 HTML 内容.它还避免了必须异步加载每个所需脚本的问题.
The simplest solution is to keep all of your scripts inline at the bottom of the page, that way they don't block the loading of HTML content while they execute. It also avoids the issue of having to asynchronously load each required script.
如果您有一个并不总是使用的特别花哨的交互,需要某种更大的脚本,那么避免在需要之前加载该特定脚本(延迟加载)可能会很有用.
If you have a particularly fancy interaction that isn't always used that requires a larger script of some sort, it could be useful to avoid loading that particular script until it's needed (lazy loading).
* scripts loaded with $.getScript
will likely not be cached
对于可以使用现代功能的任何人,例如 Promise
对象,loadScript
函数变得非常简单:
For anyone who can use modern features such as the Promise
object, the loadScript
function has become significantly simpler:
function loadScript(src) {
return new Promise(function (resolve, reject) {
var s;
s = document.createElement('script');
s.src = src;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
}
请注意,此版本不再接受 callback
参数,因为返回的 Promise 将处理回调.以前是 loadScript(src, callback)
现在是 loadScript(src).then(callback)
.
Be aware that this version no longer accepts a callback
argument as the returned promise will handle callback. What previously would have been loadScript(src, callback)
would now be loadScript(src).then(callback)
.
这具有能够检测和处理故障的额外好处,例如可以调用...
This has the added bonus of being able to detect and handle failures, for example one could call...
loadScript(cdnSource)
.catch(loadScript.bind(null, localSource))
.then(successCallback, failureCallback);
...它会优雅地处理 CDN 中断.
...and it would handle CDN outages gracefully.
这篇关于异步加载脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!