异步加载JS脚本.docx

上传人:sk****8 文档编号:3020259 上传时间:2019-05-17 格式:DOCX 页数:10 大小:66.88KB
下载 相关 举报
异步加载JS脚本.docx_第1页
第1页 / 共10页
异步加载JS脚本.docx_第2页
第2页 / 共10页
异步加载JS脚本.docx_第3页
第3页 / 共10页
异步加载JS脚本.docx_第4页
第4页 / 共10页
异步加载JS脚本.docx_第5页
第5页 / 共10页
点击查看更多>>
资源描述

1、异步加载 JS 脚本JavaScript 脚本对现代网站来说是必不可少的。当用户访问站点,需要下载各种资源,例如 JS 脚本,CSS,图片,iframe 等。浏览器下载除 JS 外的资源时,会并行下载,以提高性能。但下载 JS 脚本时,会禁止并行下载(称为脚本阻塞 Scripts Block Downloads)。浏览器遇到JS 时,必须等 JS 下载,解析,执行完后,才能继续并行下载下一个资源。原因是 JS 可能会改变页面或改变 JS 间的依赖关系,例如 A.js 中用document.write 改变页面,B.js 依赖于 A.js。因此要严格保证顺序,不能并行下载。因此不推荐将 JS 放

2、到标签里,你可以点击例子页面试一下。浏览器遇到标签会下载,解析,执行完脚本后,才继续处理剩余的页面部分。而且浏览器在遇到标签前是不会渲染页面的,因此例子中处理 JS 用了2s,页面会白屏 2s。为了避免白屏,通常的建议是将 JS 放到标签底下,可以有最佳的用户体验,你可以点击例子页面试一下。如果你放到了标签的上部,因为脚本阻塞,可能会影响用户体验。例子中位于上部的 JS 耗时 2s,因此位于JS 下面的两张 img 图片,会等 2s 后才开始加载。将 JS 放在底下的建议没有错,几乎成了前端的普世规则。但对于追求极致用户体验的站点,或大型网站来说,这还不够。虽然 JS 脚本由于存在的依赖关系,

3、需要按顺序执行,但并不需要按顺序下载。本篇就介绍一下让 JS 与其他组件并行下载的方法,即异步处理脚本。异步处理外部脚本:(按推荐度从高到低排列)Dynamic Script ElementScript asyncScript deferXHR EvalXHR InjectScript in iframe直接写入 HTMLdocument.write Script忙指示器异步处理外部脚本总结异步处理行内脚本Dynamic Script Element通常我们加载 JS 脚本会在 HTML 里:这属于静态脚本元素,浏览器执行到这里发现 script 元素,会按上面所说的,下载解析执行脚本,同时阻

4、塞其他资源文件的下载。而动态脚本元素如下:var script = document.createElement(script); /创建 script 标签script.type = “text/javascript“;script.src = “A.js“;document.getElementsByTagName(head)0.appendChild(script); /塞进页面先用 document.createElement(script)生成一个 script 标签,再设置它的 src 属性,最后将其插入到中。script 标签被插入到页面的 DOM 树后,就会开始下载 src 属

5、性指定的脚本。而且通过动态脚本元素下载脚本是异步的,不会阻塞页面的其他下载和处理过程,因此 script 标签插入中也没问题。当 JS 下载完毕后,就会立即执行。如果多个 JS 间有依赖关系,一下载完马上执行可能会出现 error。因此通常来说你应该将有依赖关系的 JS 合并成一个文件,虽然合并后 JS 文件会变大,但由于是异步下载,你几乎不会有什么损失。如果实在不方便将有依赖关系的文件合并。你需要自己指定先后顺序,通过监听 load 事件(IE 是 onreadystatechange)来确保依次加载脚本:function loadScript(url, callback)var scrip

6、t = document.createElement (“script“)script.type = “text/javascript“;if (script.readyState) /IEscript.onreadystatechange = function()if (script.readyState = “loaded“ | script.readyState = “complete“)script.onreadystatechange = null;callback(); else /Othersscript.onload = function()callback();script.

7、src = url;document.getElementsByTagName(“head“)0.appendChild(script);/严格确保 A-B-C,依次下载脚本文件loadScript(“A-delay.js“, function()loadScript(“B-delay.js“, function()loadScript(“C-delay.js“, function()console.log(“All files are loaded!“););););该技术不但简单,而且通用,且可以跨域,应该成为你的首选。Script asyncHTML5 里为 script 标签里新增了

8、async 属性,用于异步加载脚本:浏览器解析到 HTML 里的该行 script 标签,发现指定为 async,会异步下载解析执行脚本。例子页面的 DOM 结构里由于 script 在 img 图片之前,如果你的浏览器支持async 的话,就会异步加载脚本。此时 DOM 里已经有 img 元素了,所以脚本里能顺利取到 img 的 src 并弹框。该方式可以跨域。缺点是 HTML5 里新增属性,如果你需要继续支持旧版本浏览器可能需要打些补丁。Script deferscript 标签里可以设置 defer,表示延迟加载脚本:浏览器解析到 HTML 里的该行 script 标签,发现指定为 de

9、fer,会暂缓下载解析执行脚本。而是等到页面加载完毕后,才加载脚本(更精确地说,是在DOM 树构建完成后,在 window.onload 触发前,加载 defer 的脚本)。例子页面的 DOM 结构里由于 script 在 img 图片之前,如果你的浏览器支持defer 的话,就会延迟到页面加载完后才下载脚本。此时 DOM 里已经有 img 元素了,所以脚本里能顺利取到 img 的 src 并弹框。该方式可以跨域。缺点是虽然不像 async 属于 HTML5 的新属性,但 defer仍旧有旧版本浏览器不支持。(根据 w3cschool 的说法,只有 IE 浏览器支持defer,试验下来其他浏览

10、器新版均已支持 defer,所以 w3cschool 的说法已经过时)XHR Eval通过传统的 Ajax 方式,用 XMLHttpRequest(低版本 IE 中是 ActiveXObject)异步获得脚本内容后,通过 eval 执行脚本:function createRequest() try request = new XMLHttpRequest(); catch (tryMS) try request = new ActiveXObject(“Msxml2.XMLHTTP“); catch (otherMS) try request = new ActiveXObject(“Micr

11、osoft.XMLHTTP“); catch (failed) request = null; return request; var request = createRequest(); /获得一个请求对象request.onreadystatechange = function() if (request.readyState = 4) if (request.status = 200 .这个方法的优点是可以严格保证 JS 顺序,还能减少 HTTP 请求。缺点是不能享受不到浏览器缓存。由于缓存对站点来说如此的重要,因此不推荐这个方法。况且该方法会增大 HTML 体积,因此只有极少数情况下,

12、例如网站首页非常重要的内容,且 JS 代码较少时,才会考虑将 JS 直接写入 HTML 里。document.write Script在 IE 中可以用 document.write 把 script 元素写入 HTML 可以实现并行下载脚本,但下载脚本时仍旧会对其他资源造成脚本阻塞:document.write(“);document.write(“);该特性适用范围很窄,我只在 IE9 上确认过。基本不推荐。忙指示器浏览器在加载时有 4 种方式提示用户:标签页前的菊花转(见下图),左下角显示”已连接到 xxxx”(见下图),底部中央显示进度条,鼠标成漏斗状。后两者因为太丑,在现代浏览器中已

13、被隐藏,老式浏览器比较明显。上面介绍的异步方式中,通过 script 技术下载脚本会触发浏览器这些忙指示器。但 XHR 方式不会触发浏览器的忙指示器。你需要权衡哪些需要让用户知道正在下载,哪些不需要让用户知道。异步处理外部脚本总结对上面介绍的方法做一下总结。具有共通性的跨域,和忙指示器见下图:通常来说你应该放弃 document.write Script 方式。只有在很少情况下才会选用直接写入 HTML 的方式。如果资源需要跨域,你需要放弃 XHR Eval,XHR Inject,Script in iframe 方式如果需要兼容旧式浏览器,你可能需要放弃 Script async,Scrip

14、t defer常规的 方式加载外部脚本,因为有脚本阻塞问题,可能会出现白屏,页面卡等问题。程度视加载脚本耗时而定。用本篇介绍的方法来加载外部脚本可以大大改善用户体验。异步处理行内脚本直接写进 HTML 的 JS 代码虽然不存在下载的问题,但需要考虑执行速度。如果执行速度慢,同样会有脚本阻塞的问题。但相比外部脚本,处理行内脚本就简单多了。常见的方式如下:(按推荐度从高到低排列)行内脚本移到 HTML 底部:不赘述。异步执行行内脚本:耗时小用 setTimeout,等价于移到了 HTML 底部。耗时多用 window.onload。例如:function doSomething() setTime

15、out(doSomething, 0);如果行内代码执行的速度很快,像上面那样将 setTimeout 的时间设成 0 就行了。如果执行很耗时,为了逐步渲染,你可以用绑定到 window.onload 事件上:function doSomething() window.onload = doSomething;Script defer:defer 属性同样适用于行内脚本,具体参照上面,不赘述。总结看到这里你可能会很疑惑,现在大型前端开发中加载 JS,会用一些现成的加载工具,如 AMD 的 requirejs,seajs, mass,oyejs 等,它们既能异步下载,又能保证顺序,用起来又方便。知道这些有什么用呢?这就看得你的追求了,好比用 jQuery 能让新手很快速上手进行开发,但 JavaScript 基础不好,估计也只能用 jQuery 做点简单开发。理解了本篇,对你查看 seajs 等源码有好处,能让你对这些工具有更感性的认识。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育教学资料库 > 精品笔记

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。