注册异步javascript,声明性(静态)与动态

时间:2017-03-17 20:58:34

标签: javascript html asynchronous

静态声明async javascript与动态声明有什么区别吗?

静态

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript" src="https://foo.bar/myscript.js" async>
  </script>
  ...
</body>
</html>

动态

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript">
      var myScript = document.createElement("script");
      myScript.src = 'https://foo.bar/myscript.js';
      myScript.async = !0;
      myScript.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(myScript);
  </script>
  ...
</body>
</html>

我注意到静态声明一个脚本让浏览器先检测到它并预加载(chrome + firefox)。

我的目标是以async方式加载javascript,以便不阻止HTML呈现和其他脚本执行。 Sametime,我希望它在下载后立即执行,记住它需要一个元素已经在DOM中。下载后,脚本将被执行并访问my-script-needs-me div。一个限制,我不能改变脚本本身。

4 个答案:

答案 0 :(得分:2)

支持异步参数,允许此调用异步。

您描述的第二种方式允许您将url作为参数并绑定它。 它还允许在加载脚本时使用回调来执行某些操作。

let scriptElement = document.createElement('script');
let url = `https://maps.googleapis.com/maps/api/js?key=${apiKey}`;//&libraries=geometry
  scriptElement.src = url;
  //Chargement de l'API Google
  scriptElement.onload = () => {
    //API chargée, on peut lancer l'initialisation du composant
    this._initializeMap();
  };

我用它来加载谷歌地图API,它不是直接在HTML中,所以我可以在我的页面加载时修改URL。加载API时,我需要启动需要此API的处理方法。

答案 1 :(得分:1)

您可以使用defer代替异步。

您的脚本将在解析html后立即执行。

答案 2 :(得分:1)

<强>静态

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript" src="https://foo.bar/myscript.js" async>
  </script>
  ...
</body>
</html>

如您所知,HTML被解析为自上而下。因此,如果它放在body标签内,那么一旦解析,如果它是IIFE或文件myscript.js包含function call,它将立即执行。

因此,在body内部,将脚本置于底部将帮助您在div加载后执行它。

但由于缓存,我们无法保证。

如果浏览器缓存脚本,如果它是IIFE或包含函数调用,我们无法预测行为。

动态

在动态方面,它还取决于订单。

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript">
      var myScript = document.createElement("script");
      myScript.src = 'https://foo.bar/myscript.js';
      myScript.async = !0;
      myScript.type = 'text/javascript';
      document.getElementsByTagName('head')[0].appendChild(myScript);
  </script>
  ...
</body>
</html>

在这两种情况下,它都会在HTML内容之后呈现。

确保仅在加载所有内容后加载的最佳方法是

在窗口上给出eventListener

检查以下代码

<html>
<head>
  ...
</head>
<body>
  ...
  <div id='my-script-needs-me'></div>
  <script type="text/javascript">
     function load(){
        var myScript = document.createElement("script");
        myScript.src = 'https://foo.bar/myscript.js';
        myScript.async = !0;
        myScript.type = 'text/javascript';
        document.getElementsByTagName('head')[0].appendChild(myScript);
     }
     window.addEventListener("DOMContentLoaded",load);
  </script>
  ...
</body>
</html>

检查此行window.addEventListener("DOMContentLoaded",load);

DOMContentLoaded类似于jQuery的$(document).ready()。当HTML正确加载时,它将触发回调函数。因此,您不必检查是否存在HTML元素。

答案 3 :(得分:1)

据我所知,最好采用static方式声明异步脚本(在我的特定场景中),而不是dynamic。这里有一些原因:

    浏览器检测到
  1. static async脚本声明并立即启动(在页面处理的最顶部);
  2. (从#1推迟)浏览器将请求队列中的脚本请求放在更早的位置,如果您有足够的(每页加载30-40个请求),那么在前10个请求中,而不是在30-位置,这可能是至关重要的。 40;
  3. 只要整个head已经处理完毕,
  4. bodystatic动态添加脚本并不会带来任何性能优势不会延迟执行静态声明的脚本;
  5. 在我们到达脚本声明时,head将立即生效,因为它已经预先加载并准备执行(在大多数情况下,static在这里至关重要)而async 1}}脚本声明只会启动下载脚本的请求,然后才执行它;
  6. 我希望我的想法能帮助别人。