Step-By-Step icon indicating copy to clipboard operation
Step-By-Step copied to clipboard

异步加载 js 脚本的方法有哪些?

Open YvetteLau opened this issue 5 years ago • 22 comments

YvetteLau avatar Jun 12 '19 00:06 YvetteLau

1:html5中新增async(ie9以上;并且只能用于外部脚本js的引入) 2:html4中defer属性(只能用于外部脚本js的引入) 3:利用ajax请求js的代码并用eval执行 4:动态创建script标签 5:用iframe引入js 6:requirejs 7:import 8:define

shenanheng avatar Jun 12 '19 01:06 shenanheng

  1. 指定 async 属性 指定 async 属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。 为此,建议异步脚本不要在加载期间修改 DOM。 执行顺序:让脚本在加载完可用时立即执行,异步脚本一定会在页面的 load 事件前执行,但可能会在 DOMContentLoaded 事件触发之前或之 后执行。
<!DOCTYPE html>
    <html>
<head>
<title>Example HTML Page</title>
<script type="text/javascript" async src="example1.js"></script> <script type="text/javascript" async src="example2.js"></script>
      </head>
      <body>
<!-- 这里放内容 --> </body>
</html>
  1. defer属性 执行顺序:在dom加载完毕后执行,defer脚本的执行会在window.onload之前,其他没有添加defer属性的script标签之后
<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>
    <meta charset="UTF-8">
</head>
<script>
    window.onload = function() {
        console.log("window.onload");
    }
</script>
<script src="js/defer.js" defer></script>
<script>
    console.log("normal");
</script>
<body>
</body>
</html>
  1. 利用XHR异步加载js内容并执行
<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>
    <meta charset="UTF-8">
</head>
<script>
    var xhr = new XMLHttpRequest();
    xhr.open("get", "js/defer.js",true)
    xhr.send();
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            eval(xhr.responseText);
        }
    }
</script>
<body>
</body>
</html>
  1. 动态创建script标签
 var script = document.createElement("script");
  script.src = "js/test.js";
  document.head.appendChild(script);
  1. iframe 方式 用 iframe 加载一个同源的子页面,让子页面的 js 影响当前的父页面

luohong123 avatar Jun 12 '19 01:06 luohong123

  1. 动态创建script标签,可通过script的onreadyState监视加载。
  2. html5新增的async属性:可跟其他内容并行下载,限制ie9以上,只能加载外部js脚本。
  3. html4的defer,作用与async相同,兼容更好一点,但async只要加载完可立即执行,defer需等待在dom加载完毕后执行,在window.onload之前,其他没有添加defer属性的script标签之后。
  4. 利用XHR异步加载js内容并执行。
  5. iframe方式。

into-piece avatar Jun 12 '19 05:06 into-piece

1.动态创建script标签 2.利用XHR异步加载js内容并执行 3.

taoyaoyaoa avatar Jun 12 '19 05:06 taoyaoyaoa

1.给script标签添加defer属性

  • defer属性会让js并行下载,但是要等到HTML解析完成之后,在window.onload事件之前执行
  • 添加了defer属性的js文件执行的顺序和在文档中定义的顺序一样
<script src="../your_file.js" defer></script>

2.给script标签添加async属性

  • async属性会让js并行下载,但是js文件下载完成之后立刻执行无论html是否解析完毕
  • 添加了async属性的js文件执行顺序不能保证
<script src="../your_file.js" async></script>

3.动态创建script标签

  • 和img标签不一样,设置了script的src并不会开始下载,而是要添加到文档中Js文件才会开始下载
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'your_file.js';
// 只有添加到html文件中才会开始下载
document.body.append(script);

4.使用xhr脚本注入

  • 会受到同源策略的限制
 var xhr = new XMLHttpRequest();
 xhr.open("get", "your_file.js", true);
 xhr.onreadystatechange = function() {
     if (xhr.readyState == 4) {
         if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
             let script = document.createElement('script');
             script.type = 'text/javascript';
             script.src = 'your_file.js';
             script.text = xhr.responseText;
             // 只有添加到html文件中才会开始下载
             document.body.append(script);
         }
     }
 }
 xhr.send(null);

AILINGANGEL avatar Jun 12 '19 06:06 AILINGANGEL

1.脚本增加async或者defer属性 区别是async加载完成便会执行,defer要等到html解析完成之后执行 2.动态添加script标签 js代码中动态添加script标签,并将其插入页面 var script = document.createElement("script"); script.src = "a.js"; document.head.appendChild(script); 3.使用xhr异步加载并执行js 将参数设置为true(异步),进行请求

sinaine avatar Jun 12 '19 06:06 sinaine

异步加载js脚本的方法

1、

<script src="main.js" defer></script>

2、

<script src="main.js" async></script>

3、动态创建script标签

let script = document.createElement('script');
script.src = "main.js";
document.body.appendChild(script);

4、通过XHR异步加载js

let xhr = new XMLHttpRequest();
xhr.open('get', 'js/main.js', true);
xhr.onreadystatechange = function() {
    if(xhr.readyState === 4 ) {
        if(xhr.status === 200) {
            console.log(xhr.responseText)
        }
    }
}

riluocanyang avatar Jun 12 '19 06:06 riluocanyang

  1. 动态创建script标签
  2. AJAX eval(使用AJAX得到脚本内容,然后通过eval_r(xmlhttp.responseText)来运行脚本) 兼容所有浏览器。

tianyuandsb avatar Jun 12 '19 06:06 tianyuandsb

参考前面大佬的

  1. h5之前通过script标签的defer属性
<script src="index.js" defer></script>
  1. h5之后script增加了async属性
<script src="index.js" async></script>
  1. 通过动态创建script标签
let script = document.createElement('script');
script.src = "index.js";
document.body.appendChild('script');
  1. 通过XHR异步加载
let xhr = new XMLHttpRequest();
xhr.open('get', 'index.js', true);
xhr.onreadystatechange = function() {
    if(xhr.readyState === 4  && xhr.status === 200) {
        console.log(xhr.responseText)
    }
}

wangjunw avatar Jun 12 '19 06:06 wangjunw

1.在html5中,script新增了async的属性(只支持ie9以上的浏览器,只能用于加载外部js脚本) 2.在html4中,有一个defer属性,该属性的兼容性更好一点,但是与async一样,可以让js脚本实现异步加载,同样只能用于加载外部js脚本 3.利用XHR异步加载js内容并执行

<script>
    var xhr = new XMLHttpRequest();
    xhr.open("get", "js/defer.js",true)
    xhr.send();
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            eval(xhr.responseText);
        }
    }
</script>

4.动态创建script标签

var script = document.createElement("script");
    script.src = "js/test.js";
    document.head.appendChild(script);

5.iframe方式,利用iframe加载一个同源的子页面,让子页面内的js影响当前父页面的一种方式

Cain-kz avatar Jun 12 '19 10:06 Cain-kz

<script> 标签中增加 async(html5) 或者 defer(html4) 属性,脚本就会异步加载。

<script src="XXX.js" defer></script>
<script src="XXX.js" async></script>

deferasync 的区别在于:

  • defer 要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),在window.onload 之前执行;
  • async 一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
  • 如果有多个 defer 脚本,会按照它们在页面出现的顺序加载
  • 多个 async 脚本不能保证加载顺序

动态创建 script 标签

动态创建的 script ,设置 src 并不会开始下载,而是要添加到文档中Js文件才会开始下载。

let script = document.createElement('script');
script.src = 'XXX.js';
// 添加到html文件中才会开始下载
document.body.append(script);

使用xhr异步加载并执行js

let xhr = new XMLHttpRequest();
xhr.open("get", "js/defer.js",true)
xhr.send();
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        eval(xhr.responseText);
    }
}

YvetteLau avatar Jun 12 '19 12:06 YvetteLau

异步加载JS的方式

  • 动态创建
(function () {
    var dom = document.createElement('script')
    dom.type = 'text/javascript'
    dom.async = true
    dom.src= 'file.js'
    var head = document.getElementByTagName('head')[0],
    head.insertBefore(dom, head.firstChild)
})()

(function () {
 if (window.attachEvent) {
     window.attachEvent('load',  asyncload)
 } else {
     window.addEventListener('load', asyncload)
 }
 var asyncload = function () {
     var dom = document.createElement('script')
     dom.type = 'text/javascript'
     dom.async = true
     dom.src='file.js'
     var s = document.getElementByTagNames('script')[0]
     s.parentNode.insertBefore(dom, s)
 }
    
}) ()

第一种方法,执行完之前会阻止onload事件触发,可能会在onload执行额外的渲染工作, 第二种方法不会阻止onLoad的触发。

题外话: window.DOMContentLoaded 和 window.onload 的区别。前者是DOM解析完毕触发,但一些图片,视频还没有加载完,后者是页面完全加载完毕

  • XHR Eval :通过ajax获取js的内容,然后eval 插入执行
var xhr ;
if (XMLHttpRequest) {
    xhr = new XMLHttpRequest()
} else {
    xhr = new ActiveXObject('MIcrosoft.XMLHTTP')
}
xhr.open('get', 'file.js', true)
xhr.send()
xhr.onreadystatechange = function () {
    if(xhr.readyState === 4) {
       eval(xhr.responseText) 
    }
}
  • 利用iframe 引入
var iframe = document.createElement('iframe')
document.body.appendChild(iframe)
var doc = iframe.contentWindow.document
doc.open().write('<body onload=function()>');
doc.close()
  • defer 和 async

defer :浏览器会并行下载js, 等Html全部解析完毕,DOM加载完成后,再去执行js文件 ,且这种方式只能用

async: 异步下载后立即执行,H5新增的。按那个js先下载完先执行的远着

yelin1994 avatar Jun 12 '19 14:06 yelin1994

1.script 标签中增加 asyncdefer 属性;

  • defer属性:异步下载文件,按照顺序执行带有defer的属性的script标签;在文档渲染完毕后,DOMContentLoaded之前执行;
  • async属性:先加载完先执行;执行时,会阻塞文档渲染;

2.动态创建 script 标签; 3.父窗口插入 iframe 元素,在 iframe 中加载js; 4.document.write; 5.XHR Injection 方式。创建 script 元素插入到 DOM 结构中,ajax 请求成功后设置 script.text; 6.XHR eval 方式。ajax 请求成功后放在 eval 中执行;

daibin0809 avatar Jun 12 '19 14:06 daibin0809

1: 在html5中,script新增了async的属性,script添加了该属性之后,下载脚本时将可以与页面其他内容并行下载,但是该属性必须在ie9以上的浏览器中才可以使用,并且只能用于加载外部js脚本。
<script src="js/async.js" async></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js" async="async"></script>

2: 同样,在html4中也有一个defer属性,该属性的兼容性更好一点,但是与async一样,可以让js脚本实现异步加载,同样只能用于加载外部js脚本。
<script src="js/defer.js" defer></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js" defer="defer"></script>
asyc与defer属性的不同点是:async会让脚本在加载完可用时立即执行,而defer脚本则会在dom加载完毕后执行,defer脚本的执行会在window.onload之前,其他没有添加defer属性的script标签之后。

3: 利用XHR异步加载js内容并执行
<!DOCTYPE html>
<html lang="en">
  <head>
  <title></title>
  <meta charset="UTF-8">
  </head>
  <script>
var xhr = new XMLHttpRequest();
xhr.open("get", "js/defer.js",true)
xhr.send();
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
      eval(xhr.responseText);
    }
  }
  </script>
  <body>
  </body>
  </html>

4:动态创建script标签
function loadScript(url, callback){
  var script = document.createElement("script");
  script.type = "text/javascript";
  if (script.readyState){ //IE
    script.onreadystatechange = function(){
      if (script.readyState == "loaded" ||
        script.readyState == "complete"){
        script.onreadystatechange = null;
        callback();
      }
    };
  } else { // Others: Firefox, Safari, Chrome, and Opera
    script.onload = function(){
      callback();
    };
  }
  script.src = url;
  document.body.appendChild(script);
}
该方式还可以通过script的onreadyState监视加载的状态。

5:iframe方式,利用iframe加载一个同源的子页面,让子页面内的js影响当前父页面的一种方式。

6: 延迟加载
// 5秒后执行
varstart = Number(newDate());
while(start + 5000 > Number(newDate())){//执行JS}

7: $(document).ready()
  需要引入jquery
  兼容所有浏览器
  $(document).ready(function() {
    alert("加载完成!");
  });













Yuko7245 avatar Jun 12 '19 15:06 Yuko7245

  1. H5新增属性 async Chrome、Firefox、IE9&IE9+均支持(IE6~8不支持)。
  1. H4的属性 defer 兼容所有浏览器。

这两个方法的区别 1、defer脚本的执行会在window.onload之前,其他没有添加defer属性的script标签之后。 2、async会让脚本在下载完可用时立即执行,而defer脚本则会在dom加载完毕后执行, 3、async不能确保加载执行的顺序,多个 defer 脚本,会按照它们在页面出现的顺序加载

async 3.动态创建script标签

(function () {
        var s = document.createElement_x('script'); 
        s.type = 'text/javascript';
        s.src = "http://code.jquery.com/jquery-1.7.2.min.js";
        var tmp = document.getElementsByTagName_r('script')[0];
        tmp.parentNode.insertBefore(s, tmp);
    })();

4.XHR异步加载js

 var xhr = new XMLHttpRequest();
    xhr.open("get", "xxxx.js", true)
    xhr.send();
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            eval(xhr.responseText);
        }
    }

5.iframe方式,利用iframe加载一个同源的子页面,让子页面内的js影响当前父页面的一种方式。

0xBrooke avatar Jun 12 '19 17:06 0xBrooke

异步加载的很多 1.async 在html5新增的属性,谷歌、火狐、ie9(ie6-ie8)不支持

2.H4属性中的defer 兼容所有浏览器

3.两个方法的区别

1、defer脚本的执行会在window.onload之前,其他没有添加defer属性的script标签之后。

2、async会让脚本在下载完可用时立即执行,而defer脚本则会在dom加载完毕后执行,

3、async不能确保加载执行的顺序,多个 defer 脚本,会按照它们在页面出现的顺序加载

web-data-MrLi avatar Jun 13 '19 08:06 web-data-MrLi

script标签有两个属性 defer 和async

defer 并行加载脚本,在解析该 script标签时并不会阻止文档的渲染 ,defer属性的script脚本必须等到dom结构渲染完毕才可以执行。

async

同步加载脚本,当解析该脚本时,会将该脚本的内容解析完毕之后,再去进行dom的绘制,造成文档加载阻塞

常见的异步加载脚本的方式

1. 动态创建scipt标签:

var script = document.creamentElement('script');

 script.src='a.js'

document.body.append(script)

2 .XHR异步加载:

var xhr =new xhrHttpRequest()  
 xhr.open(get, 'a.js', true)
 xhr.send()
 xhr.onreadystatechange=function(){
   if(xhr.status===200  || xhr.readyState===4){
       eval(xhr.responseText)
   }
 }

chongyangwang avatar Jun 16 '19 06:06 chongyangwang

浏览器加载JS文件的原理 浏览器加载Javascript脚本,主要通过

异步加载 1. 这其实不算异步加载,但这也是常见的通过改变JS加载方式来提升页面性能的一种方式。 不会造成页面解析阻塞,就算加载时间过长,用户也可以看到页面,而不是一片空白,而且这个时候可以在脚本中操作DOM。 2.defer属性 通过给

3.async属性 async属性和defer属性类似,也会开启一个线程去下载JS文件,但是和defer不同的是,它会在下载后立刻执行,而不会等到DOM加载完成后再执行,所以还是会造成阻塞。 同样的,async也只适用于外部JS文件,也不能在js中使用document.write方法,但是对于多个带有async的JS文件,它不能像defer那样保证按顺序执行,它是哪个JS文件先下载完就先执行哪个文件。

  1. 动态创建
(function(){
   var scriptElement=document.createElement("script");
   scriptElement.type="text/javascript";
   scriptElement.async=true;
   scriptElement.src="http://cdn.bootscss.com/jquery/3.0.0-beta1/jquery.min.js";
   var x=document.getElementByTagName("head")[0];
   x.insertBefore(scriptElement,x.firstChild);
})()

或者

(function(){
if(window.attachEvent){//针对IE
      window.attachEvent("onload",asyncLoad);
} else {
      window.addEventListener("load",asyncLoad);
}
var asyncLoad= function(){
   var ga=document.createElement('script');
   ga.type="text/javascript";
   ga.async= true;
   ga.src=('https:'==document.location.protocol?"https://ssl":"http://www")+'.google-analytics.com/ga.js';
   var s=document.getElementByTagName('script')[0];
   s.parentNode.insertBefore(ga,s);
  
}
})();

attachEvent和addEventListener的区别 https://www.cnblogs.com/dacuotecuo/p/3510823.html

第一种方法在脚本执行完之前,还是会阻止onload事件的触发,第二种则不会。 window.DOMContentLoaded和window.onload区别 前者是DOM解析完毕之后触发,JS可以获取到DOM引用,但是页面中的一些资源比如图片和视频还没有加载完成,作用同jQuery中的ready事件。后者则是页面全部加载完毕,包含各种资源。

何时用defer何时用async? 两者选择要看脚本间有没有依赖关系,有依赖要保证执行顺序,用defer没有依赖的话用async。 两者同时使用defer失效。两者都不能用document.write会导致整个页面被清除。

image

5.XHR异步加载

var xhr =new xhrHttpRequest()  
 xhr.open(get, 'a.js', true)
 xhr.send()
 xhr.onreadystatechange=function(){
   if(xhr.status===200  || xhr.readyState===4){
       eval(xhr.responseText)
   }
 }

转载自:酥风 https://juejin.im/post/5bcdaed7e51d457a8254e1b7

jodiezhang avatar Jun 16 '19 10:06 jodiezhang

异步加载JS的方法

这个布尔属性被设定用来通知浏览器该脚本将在文档完成解析后,触发 DOMContentLoaded 事件前执行。如果缺少 src 属性(即内嵌脚本),该属性不应被使用,因为这种情况下它不起作用。对动态嵌入的脚本使用 async=false 来达到类似的效果。

该布尔属性指示浏览器是否在允许的情况下异步执行该脚本。该属性对于内联脚本无作用 (即没有src属性的脚本)。

  1. JS异步创建
setTimeout(function () {
var script = document.createElement('script')
script.src = 'xxx';
document.querySelector('body').appendChild(script)
}, 0);

KRISACHAN avatar Jun 18 '19 01:06 KRISACHAN

异步加载js脚本的方法

我自己能想到的

  1. defer (异步下载后,按照加载顺序执行脚本)
  2. async (异步下载后乱序执行)
  3. 使用XMLHttpRequest异步请求脚本

别人补充的

  1. 动态创建 script标签
let script = document.createElement('script');
script.src = "main.js";
document.body.appendChild(script);
  1. iframe方式

ZadaWu avatar Jun 19 '19 08:06 ZadaWu

1.指定async属性 2.指定defer属性 defer要等到整个页面在内存中正常渲染结束,在window.onload之前执行 async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再进行渲染 如果有多个defer脚本,会按照顺序加载 如果多个async脚本,并不能保证加载顺序 3.利用XHR异步加载js内容并执行 4.动态创建script标签 5.iframe方式

Diamondjcx avatar Jun 25 '19 07:06 Diamondjcx

defer 属性& anync

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>defer</title>
    <script>
        window.onload = function() {
            console.log("window.onload");
        }
    </script>
    <script src="./defer.js" defer></script>
   <script src="./defer.js" async></script>
</head>
<body>
    
</body>
</html>

动态的创建js

(function(){
   var dom = document.createElement('script');
   dom.type ='text/javascript';
   dom.async = true;
   dom.src= 'file.js';
   head = document.getElementsByTagName('head')[0];
   head.insertBefore(dom,head.firstChild)
})()

XHR

let xhr  =  new XMLHttpRequest();
xhr.open('get','index.js',true)
xhr.send();
xhr.onreadystatechange = function() {
   if(xhr.readyState == 4 && xhr.status == 200){
         console.log(xhr.responseText);
   }
}

MissNanLan avatar Jul 07 '19 03:07 MissNanLan