JavaScript:如何异步下载JS?
,我正在尝试以尽可能快的速度完成页面加载 我注意到我的JavaScript似乎没有异步加载。图片链接如下 我的网站的工作原理是需要加载两个外部JavaScript文件:JavaScript:如何异步下载JS?,javascript,google-maps,asynchronous,Javascript,Google Maps,Asynchronous,,我正在尝试以尽可能快的速度完成页面加载 我注意到我的JavaScript似乎没有异步加载。图片链接如下 我的网站的工作原理是需要加载两个外部JavaScript文件: GoogleMapsV3JavaScript,以及 JQuery JavaScript 然后,我在HTML中使用了内联JavaScript,在下载上述两个文件之前无法执行 一旦加载这些外部javascript文件,它就可以动态呈现页面。在谷歌地图和JQuery加载之前,我的页面无法加载的原因是,我的页面基于用户的地理定位(
- GoogleMapsV3JavaScript,以及
- JQuery JavaScript
尽管下面有3个答案,但没有一个能真正回答我的问题。如果有任何帮助,我们将不胜感激。HTTP下载通常受浏览器限制,每个域只能同时下载两次。这就是为什么有些网站在www.domain.tla上有动态内容的原因 但是浏览器对脚本的操作略有不同
标准的解决方案是将脚本移动到页面底部,但有一种解决方法可能对您有效,也可能对您无效:。无论脚本以何种顺序下载,都应按照脚本在页面上出现的顺序解析/执行脚本(除非您使用“延迟”) 所以,你可以先把谷歌地图和JQuery放在头上。然后,在页面正文的某个地方:
<script language="Javascript">
function InitPage() {
// Do stuff that relies on JQuery and Google, since this script should
// not execute until both have already loaded.
}
$(InitPage); // this won't execute until JQuery is ready
</script>
您可以使用类似的东西,这在大多数浏览器中都非常有效。至少在IE6中有一些问题,但我没有时间去调查
var require = function (scripts, loadCallback) {
var length = scripts.length;
var first = document.getElementsByTagName("script")[0];
var parentNode = first.parentNode;
var loadedScripts = 0;
var script;
for (var i=0; i<length; i++) {
script = document.createElement("script");
script.async = true;
script.type = "text/javascript";
script.src = scripts[i];
script.onload = function () {
loadedScripts++;
if (loadedScripts === length) {
loadCallback();
}
};
script.onreadystatechange = function () {
if (script.readyState === "complete") {
loadedScripts++;
if (loadedScripts === length) {
loadCallback();
}
}
};
parentNode.insertBefore(script, first);
}
};
有人让我对这个帖子发表评论,但那是在@lonut发布回复之前@lonut的代码是一个非常好的解决方案,但我有一些评论(批评和不那么批评): 首先,@lonut的代码假定脚本对其他脚本没有负载依赖关系。这有点难以解释,所以让我们使用jquery.min.js和prototype.js的简单示例。假设我们有一个简单的页面,只加载以下两个脚本:
<script src="jquery.min.js"></script>
<script src="prototype.js"></script>
记住-页面中没有其他内容-没有其他JavaScript代码。如果加载该页面,两个脚本将被下载,一切正常。现在,如果删除jquery.min.js脚本会发生什么?如果由于prototype.js试图引用jquery.min.js中定义的符号而从prototype.js中得到错误,那么prototype.js对jquery.min.js具有加载依赖关系-除非已经加载jquery.min.js,否则无法加载prototype.js。但是,如果没有得到任何错误,则可以按照您希望的任何顺序加载这两个脚本。假设您的外部脚本之间没有负载依赖关系,@lonut的代码非常棒。如果您确实有负载依赖关系,那么它会变得非常困难,您应该在更快的网站上阅读第4章
其次,@lonut代码的一个问题是,某些版本的Opera将调用loadCallback两次(一次从onload处理程序调用,另一次从onreadystatechange处理程序调用)。只需添加一个标志,以确保loadCallback只调用一次
第三,现在大多数浏览器每个主机名打开的连接超过2个。请参阅。动态脚本加载器是专门为这种情况设计的。例如,您可以执行以下操作:
$LAB
.script("googlemaps.js")
.script("jquery.js")
.wait(function(){
// yay, both googlemaps and jquery have been loaded, so do something!
});
$LAB
.script("jquery.js")
.wait() // make sure jquery is executed first
.script("plugin.jquery.js")
.script("googlemaps.js")
.wait(function(){
// all scripts are ready to go!
});
如果情况稍微复杂一点,并且您有一些脚本相互依赖,正如Steve Souders所提到的,那么您可以:
$LAB
.script("googlemaps.js")
.script("jquery.js")
.wait(function(){
// yay, both googlemaps and jquery have been loaded, so do something!
});
$LAB
.script("jquery.js")
.wait() // make sure jquery is executed first
.script("plugin.jquery.js")
.script("googlemaps.js")
.wait(function(){
// all scripts are ready to go!
});
无论哪种情况,LABjs都将并行下载所有脚本(“jquery.js”、“googlemaps.js”和“plugin.jquery.js”),至少在浏览器允许的范围内。但是通过在链中明智地使用.wait(),LABjs将确保它们以正确的顺序执行。也就是说,如果链中的两个脚本之间没有.wait(),它们将尽快执行(表示tehm之间的顺序不确定)。如果链中的两个脚本之间有一个.wait(),那么第一个脚本将在第二个脚本之前执行,即使它们是并行加载的。移动您的javascript包含(
以下是我如何在jquery mobile上异步加载GMAP的:
首先,您可以加载jquery(即,使用上面IonuțG.Stan发布的require函数)
然后,您可以使用gmaps中的回调参数执行以下操作:
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
var require = function (scripts, loadCallback) {
var length = scripts.length;
var first = document.getElementsByTagName("script")[0];
var parentNode = first.parentNode;
var loadedScripts = 0;
var script;
for (var i=0; i<length; i++) {
script = document.createElement("script");
script.async = true;
script.type = "text/javascript";
script.src = scripts[i];
script.onload = function () {
loadedScripts++;
if (loadedScripts === length) {
loadCallback();
}
};
script.onreadystatechange = function () {
if (script.readyState === "complete") {
loadedScripts++;
if (loadedScripts === length) {
loadCallback();
}
}
};
parentNode.insertBefore(script, first);
}
};
require([
"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",], function () {
$.ajax({
type: "GET",
url: 'http://maps.googleapis.com/maps/api/js?v=3&sensor=false&callback=setMyMap',
dataType: "script"
});
});
function setMyMap() {
console.log('your actions here');
var coords = new google.maps.LatLng(40.5439532,-3.6441775);
var mOptions = {
zoom: 8,
center: coords,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("gmap"), mOptions);
}
</script>
<div id="gmap" style="width:299px; height:299px"></div>
</body>
var require=函数(脚本、loadCallback){
var length=scripts.length;
var first=document.getElementsByTagName(“脚本”)[0];
var parentNode=first.parentNode;
var loadedScripts=0;
var脚本;
对于(var i=0;i使用requireJS可以实现您心中的目标。requireJS异步下载js资源。这是一个非常简单和有用的实现库。请在这里阅读更多内容。这也是我的第一个想法,但这两个脚本实际上都来自不同的域。毕竟,我只是说:这是浏览器specific行为。在Firefox中,每个域的下载可以配置为network.http.max connections
中的about:config
。默认为15。@BalusC:下载javascript文件会阻止所有其他下载,而不考虑域。此外,de