Home >Web Front-end >JS Tutorial >Detailed explanation of Javascript asynchronous loading (browser loading method in javascript)_javascript skills

Detailed explanation of Javascript asynchronous loading (browser loading method in javascript)_javascript skills

WBOY
WBOYOriginal
2016-05-16 17:53:451108browse
1. The forms of synchronous loading and asynchronous loading
1. Synchronous loading
The most commonly used form of synchronous loading is this:

Synchronous mode, also known as blocking mode, will prevent the browser from subsequent processing, stop subsequent parsing, and therefore stop subsequent file loading (such as images), rendering, code execution.
The reason why js needs to be executed synchronously is because there may be behaviors such as outputting document content, modifying dom, redirection, etc. in js, so synchronous execution is safe by default.
The previous general recommendation was to place <script> at the end of the page before </body> to minimize this blocking behavior and allow the page to be displayed first. <br>Simply put: the loaded network timeline is a waterfall model, while the asynchronously loaded timeline is a concurrency model. <br>2. Common asynchronous loading (Script DOM Element) <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="90073" class="copybut" id="copybut90073" onclick="doCopy('code90073')"><u>Copy code </u></a></span> The code is as follows: </div> <div class="codebody" id="code90073"> <br>(function() { <br>var s = document.createElement('script'); <br>s.type = 'text/javascript'; <br>s.async = true; <br>s.src = 'http://yourdomain.com/script.js'; <br>var x = document.getElementsByTagName('script')[0]; <br>x.parentNode.insertBefore(s, x); <br>} )(); <br> </div> <br>Asynchronous loading is also called non-blocking. The browser will continue to process subsequent pages while downloading and executing js. <br>This method is to use js to create a script element within the <script> tag on the page and insert it into the document. This achieves non-blocking downloading of js code. <br>The async attribute is a new asynchronous support in HTML5. See the explanation below. It is good to add it (it will not affect it if you don’t add it). <br>This method is called the Script DOM Element method and does not require js to have the same origin. <br>The method of wrapping js code in an anonymous function and executing it immediately is to protect the variable name from leaking to the outside world. This is a very common method, especially commonly used in js libraries. <br>For example, both Google Analytics and Google Badge use this asynchronous loading code: <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="81787" class="copybut" id="copybut81787" onclick="doCopy('code81787')"><u>Copy the code</u></a></span> The code is as follows:</div> <div class="codebody" id="code81787"> <br>(function() { <br>var ga = document.createElement('script'); <br>ga.type = 'text/javascript'; ga.async = true; <br>ga. src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') '.google-analytics.com/ga.js'; <br>var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); <br>})(); <br><br>(function() <br>{var po = document. createElement("script"); <br>po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js"; <br>var s = document.getElementsByTagName("script")[0]; <br>s.parentNode.insertBefore(po, s); <br>})(); <br> </div> <br>However, this This loading method will prevent the onload event from being triggered before the loading is completed. However, the code of many pages now has to perform additional rendering work during onload, so it will still block the initialization processing of some pages. <br><br><br>3. Asynchronous loading during onload<br><div class="codetitle"> <span><a style="CURSOR: pointer" data="59761" class="copybut" id="copybut59761" onclick="doCopy('code59761')"><u>Copy code</u></a></span> The code is as follows:</div> <div class="codebody" id="code59761"> <br>(function() { <br>function async_load(){ <br>var s = document.createElement('script'); <br>s.type = 'text/javascript'; <br>s. async = true; <br>s.src = 'http://yourdomain.com/script.js'; <br>var x = document.getElementsByTagName('script')[0]; <br>x.parentNode. insertBefore(s, x); <br>} <br>if (window.attachEvent) <br>window.attachEvent('onload', async_load); <br>else <br>window.addEventListener('load', async_load , false); <br>})(); <br> </div> <br>This is similar to the previous method, but the key is that it does not start asynchronous loading of js immediately, but starts asynchronous loading only when onload. This solves the problem of blocking the onload event from being triggered. <br>Added: DOMContentLoaded and OnLoad events <br>DOMContentLoaded: The page (document) has been parsed and the dom elements in the page are available. However, the images and subframes referenced in the page may not have been loaded yet. <br>OnLoad: All resources of the page have been loaded (including images). The browser's loading progress stops at this point. <br>These two time points divide the page loading timeline into three stages. <br>4. Other methods of asynchronous loading <br>Due to the dynamic nature of Javascript, there are many asynchronous loading methods: <br>XHR Eval <br>XHR Injection <br>Script in Iframe <br>Script Defer <br> document.write Script Tag <br>Another method is to use setTimeout to delay 0 seconds in combination with other methods. <br>XHR Eval: Get the content of js through ajax, and then execute it via eval. <br>var xhrObj = getXHRObject(); <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="99282" class="copybut" id="copybut99282" onclick="doCopy('code99282')"><u>Copy code </u></a></span> The code is as follows: </div> <div class="codebody" id="code99282"> <br>xhrObj. onreadystatechange = <br>function() { <br>if ( xhrObj.readyState != 4 ) return; <br>eval(xhrObj.responseText); <br>}; <br>xhrObj.open('GET', ' A.js', true); <br>xhrObj.send(''); <br> </div> <br>Script in Iframe: Create and insert an iframe element to let it execute js asynchronously. <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="80719" class="copybut" id="copybut80719" onclick="doCopy('code80719')"><u>Copy code </u></a></span> The code is as follows: </div> <div class="codebody" id="code80719"> <br>var iframe = document.createElement('iframe'); <br>document.body.appendChild(iframe); <br>var doc = iframe.contentWindow.document; <br>doc.open().write('<body onload="insertJS()">') ; <br>doc.close(); <br> </div> <br>GMail Mobile: The content of the js in the page is commented, so it will not be executed. Then when needed, get the text content in the script element and remove the comments Then eval is executed. <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="62965" class="copybut" id="copybut62965" onclick="doCopy('code62965')"><u>Copy code</u></a></span> The code is as follows:</div> <div class="codebody" id="code62965"> <br><script type="text/javascript"> <br>/* <br>var ... <br>*/ <br></script>

See the two handouts from Steve Souders and Taobao at the 2010 Velocity Conference in the reference materials for details.

2. async and defer attributes

1. defer attribute
defer attribute declares that there will be no document.write or dom modifications in this script.
The browser will download file.js and other scripts with defer attributes in parallel without blocking subsequent processing of the page.
The defer attribute was implemented in IE 4.0, more than 13 years ago! Firefox supports the defer attribute starting from 3.5.
Note: All defer scripts are guaranteed to be executed in order.
2. async attribute

The async attribute is new to HTML5. The function is similar to defer, but it will be executed as soon as possible after downloading. There is no guarantee that the script will be executed in order. They will complete before the onload event.
Firefox 3.6, Opera 10.5, IE 9 and the latest Chrome and Safari all support the async attribute. You can use async and defer at the same time, so that all IE after IE 4 support asynchronous loading.
3. Detailed explanation of the difference between the
<script> tag in HTML 4.01 and HTML5: The <br>type attribute is required in HTML 4 and optional in HTML5. <br>The async attribute is new in HTML5. <br>Some attributes (xml:space) are not supported in HTML5. <br>Note: <br>Without the async attribute, the script will be obtained (downloaded) and executed immediately before continuing with subsequent processing, which blocks the browser's subsequent processing. <br>If there is async attribute, then the script will be downloaded and executed asynchronously, while the browser continues subsequent processing. <br>There is a defer attribute in HTML4, which prompts the browser that this script will not generate any document elements (no document.write), so the browser will continue subsequent processing and rendering. <br>If there is no async attribute but there is defer attribute, then the script will be executed after the page is parsed. <br>If both are set at the same time, the defer attribute is mainly to allow old browsers that do not support the async attribute to process it in the original defer method instead of the synchronous method. <br>Also see the official description: script async <br>Personal supplement: <br>Since HTML5 already supports asynchronous loading, why do you still need to use the troublesome method (dynamically creating script elements) recommended earlier? <br>Answer: Old browsers do not support async for compatibility. If all browsers support it in the future, adding the async attribute directly to the script is the easiest way. <br><br><br>3. Lazy loading <strong> </strong><br>We have solved the problem of asynchronous loading (async loading) before, let’s talk about what lazy loading is. <br>Lazy loading: Some js codes are not needed immediately when the page is initialized, but are needed in certain situations later. Lazy loading means that these temporarily unused js are not loaded at the beginning, but are loaded asynchronously through js control when needed or later. <br>That is, js is divided into many modules. When the page is initialized, only the js that need to be executed immediately are loaded, and then the loading of other js is delayed until the first time it is needed. <br>Especially when the page is composed of a large number of different modules, many of which may not be used temporarily or not at all. <br> Just like lazy loading of images, the image is loaded and displayed when the image appears in the visible area (when the scroll bar is pulled down). <br><br><br>4. Two-stage loading and lazy execution of scripts <strong><br></strong>JS loading actually consists of two stages: download bytes and execution (parse and execute). <br>The browser will parse and execute the js content immediately after downloading it, whether it is loaded synchronously or asynchronously. <br>The asynchronous loading mentioned earlier only solves the problem during the download phase, but the code will be executed immediately after downloading. <br>The browser blocks any operations during the JS parsing and execution phase, and the browser is in a non-responsive state at this time. <br>We all know that downloading scripts through the Internet takes significant time, but it is easy to overlook the second stage, which also takes time to parse and execute. The parsing and execution of scripts takes more time than we think, especially when there are many large scripts. Some need to be executed immediately, while others do not (for example, they are only needed when displaying a certain interface or performing an operation). <br>These scripts can be executed lazily, downloaded and cached asynchronously first, but not executed immediately, but executed once when needed for the first time. <br>Special techniques can be used to separate downloading and execution (thanks again to the dynamic nature of javascript). For example, the JS content is loaded and cached as an Image or object object, so it will not be executed immediately, and then executed when needed for the first time. <br>For more explanations of this section, please see the relevant links to ControlJS in Resources at the end. <br>Tips: <br>1. Simulate a long download time: <br>Write a back-end script and let it sleep for a certain period of time. For example, Thread.sleep(5000); in jsp, so that the content can be received after 5 seconds. <br>2. 模拟较长的 js 代码执行时间(因为这步一般比较快不容易观察到): <br>var t_start = Number(new Date()); <br>while ( t_start + 5000 > Number(new Date()) ) {} <br>这个代码将使 js 执行5秒才能完成! <br><br><strong>五、script 标签使用的历史 <br></strong><br>1. script 放在 HEAD 中 <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="89669" class="copybut" id="copybut89669" onclick="doCopy('code89669')"><u>复制代码</u></a></span> 代码如下:</div> <div class="codebody" id="code89669"> <br><head> <br><script src=“…”></script>


阻止了后续的下载;
在IE 6-7 中 script 是顺序下载的,而不是现在的 “并行下载、顺序执行” 的方式;
在下载和解析执行阶段阻止渲染(rendering);
2. script 放在页面底部(2007)
...



不阻止其它下载;
在IE 6-7 中 script 是顺序下载的;
在下载和解析执行阶段阻止渲染(rendering);
3. 异步加载script(2009)
复制代码 代码如下:

var se = document.createElement('script');
se.src = 'http://anydomain.com/A.js';
document.getElementsByTagName('head')
[0].appendChild(se);


这就是本文主要说的方式。
不阻止其它下载;
在所有浏览器中,script都是并行下载;
只在解析执行阶段阻止渲染(rendering);
4. 异步下载 + 按需执行 (2010)
复制代码 代码如下:

var se = new Image();
se.onload = registerScript();
se.src = 'http://anydomain.com/A.js';

把下载 js 与 解析执行 js 分离出来
不阻止其它下载;
在所有浏览器中,script都是并行下载;
不阻止渲染(rendering)直到真正需要时;
六、异步加载的问题
在异步加载的时候,无法使用 document.write 输出文档内容。
在同步模式下,document.write 是在当前 script 所在的位置输 出文档的。而在异步模式下,浏览器继续处理后续页面内容,根本无法确定 document.write 应该输出到什么位置,所以异步模式下 document.write 不可行。而到了页面已经 onload 之后,再执行 document.write 将导致当前页面的内容被清空,因为它会自动触发 document.open 方法。
实际上document.write的名声并不好,最好少用。
替代方法:
1. 虽然异步加载不能用 document.write,但还是可以onload之后执行操作dom(创建dom或修改dom)的,这样可以实现一些自己的动态输出。比如要在页面异步创建一个浮动元素,这和它在页面中的位置就没关系了,只要创建出该dom元素添加到 document 中即可。
2. 如果需要在固定位置异步生成元素的内容,那么可以在该固定位置设置一个dom元素作为目标,这样就知道位置了,异步加载之后就可以对这个元素进行修改。
六、JS 模块化管理
异步加载,需要将所有 js 内容按模块化的方式来切分组织,其中就存在依赖关系,而异步加载不保证执行顺序。
另外,namespace 如何管理 等相关问题。这部分已超出本文内容,可参考:
RequireJS 、 CommonJS 以及 王保平(淘宝)的 SeaJS 及其博客 。
七、JS最佳实践:
1. 最小化 js 文件,利用压缩工具将其最小化,同时开启http gzip压缩。工具:
2. 尽量不要放在 中,尽量放在页面底部,最好是之前的位置
3. 避免使用 document.write 方法
4. 异步加载 js ,使用非阻塞方式,就是此文内容。
5. 尽量不直接在页面元素上使用 Inline Javascript,如onClick 。有利于统一维护和缓存处理。
参考资料:
Lazy Loading Asyncronous Javascript
Load Non-blocking JavaScript with HTML5 Async and Defer
Two handouts from Velocity China 2010:
Steve Souders(Google)'s Even Faster Web Sites (pdf)
Li Mu (Taobao)'s Third-party advertising code stability and performance optimization practice (pdf)
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:jQuery loop scrolling display code can be applied to text and pictures_jqueryNext article:jQuery loop scrolling display code can be applied to text and pictures_jquery

Related articles

See more