JavaScript:如何异步下载JS?

JavaScript:如何异步下载JS?,javascript,google-maps,asynchronous,Javascript,Google Maps,Asynchronous,,我正在尝试以尽可能快的速度完成页面加载 我注意到我的JavaScript似乎没有异步加载。图片链接如下 我的网站的工作原理是需要加载两个外部JavaScript文件: GoogleMapsV3JavaScript,以及 JQuery JavaScript 然后,我在HTML中使用了内联JavaScript,在下载上述两个文件之前无法执行 一旦加载这些外部javascript文件,它就可以动态呈现页面。在谷歌地图和JQuery加载之前,我的页面无法加载的原因是,我的页面基于用户的地理定位(

,我正在尝试以尽可能快的速度完成页面加载

我注意到我的JavaScript似乎没有异步加载。图片链接如下

我的网站的工作原理是需要加载两个外部JavaScript文件:

  • GoogleMapsV3JavaScript,以及
  • JQuery JavaScript
然后,我在HTML中使用了内联JavaScript,在下载上述两个文件之前无法执行

一旦加载这些外部javascript文件,它就可以动态呈现页面。在谷歌地图和JQuery加载之前,我的页面无法加载的原因是,我的页面基于用户的地理定位(使用GMAP),然后根据它们所在的位置(例如纽约、旧金山等)显示页面。也就是说,两个在不同城市浏览我的网站的人会看到不同的首页

问题:如何让JavaScript文件异步下载,以使整个页面加载时间最快

更新

如果我以某种方式异步下载GoogleMaps和JQuery,我将如何创建一个事件,一旦GoogleMaps和JQuery都下载了,该事件将被触发,因为我的页面对这些文件有很强的依赖性来执行

更新2


尽管下面有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