這篇文章給大家分享的是有關(guān)處理JavaScript異步加載的注意事項(xiàng)有哪些的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
創(chuàng)新互聯(lián)是專業(yè)的長安網(wǎng)站建設(shè)公司,長安接單;提供做網(wǎng)站、網(wǎng)站制作,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行長安網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!
處理JavaScript異步加載詳解的注意事項(xiàng)有哪些
同步加載的問題
默認(rèn)的js是同步加載的,這里的“加載”可以理解成是解析、執(zhí)行,而不是“下載”,在最新版本的瀏覽器中,瀏覽器對于代碼請求的資源都是瀑布式的加載,而不是阻塞式的,但是js的執(zhí)行總是阻塞的。這會引起什么問題呢?如果我的index頁面要加載一些js,但是其中的某個請求遲遲得不到響應(yīng),于是阻塞了后面的js代碼的執(zhí)行(同步加載),同時頁面渲染也不能繼續(xù)(如果js引入是在head標(biāo)簽后)。
this is a test
比如上面的這段代碼,保存為index.html文件,頁面的主體是一個簡單的字符串,但是代碼執(zhí)行后頁面遲遲都是空白,為何?因?yàn)檎埱蟮膉s遲遲無法加載(可能由于谷歌被墻等原因),于是阻塞了后面的代碼的執(zhí)行,頁面得不到渲染。可能你會提議,把js代碼放到
前不就能先渲染頁面了!好方法,我們嘗試著將js放后面:
this is a test
頁面瞬間被渲染,“this is a test"也很快出現(xiàn)在前臺,世界似乎平靜了,可是:
this is a test
在前面代碼的基礎(chǔ)上簡單加了一段代碼,但是"hello world"遲遲無法在控制臺輸出,顯然前面的js請求阻塞了后面代碼的加載,我們恍然大悟,改變js的加載位置只能改變頁面的渲染,然而對于js的加載并沒有什么卵用,js還是會阻塞。
我們的要求似乎很簡單,能在頁面加載的同時,在控制臺輸出字符串即可,再講的通俗一點(diǎn),就是在請求第一段谷歌提供的js的同時,繼續(xù)執(zhí)行下面的js,也就是實(shí)現(xiàn)js的異步加載。
最常見的做法是動態(tài)生成script標(biāo)簽:
this is a test
但是還是有點(diǎn)問題,這種加載方式在加載執(zhí)行完之前會阻止 onload 事件的觸發(fā),而現(xiàn)在很多頁面的代碼都在 onload 時還要執(zhí)行額外的渲染工作等,所以還是會阻塞部分頁面的初始化處理:
this is a test
比如上面的代碼不能很好地渲染”hello world”,我們只需將注釋去掉就可以了,讓谷歌提供的js在onload 時才開始異步加載。這樣就解決了阻塞 onload 事件觸發(fā)的問題。
補(bǔ)充DOMContentLoaded 與 OnLoad 事件 DOMContentLoaded : 頁面(document)已經(jīng)解析完成,頁面中的dom元素已經(jīng)可用。但是頁面中引用的圖片、subframe可能還沒有加載完。 OnLoad:頁面的所有資源都加載完畢(包括圖片)。瀏覽器的載入進(jìn)度在這時才停止。這兩個時間點(diǎn)將頁面加載的timeline分成了三個階段。
以上似乎能較好解決這個問題,但是html5提供了更簡便的方法,async屬性!
this is a test
async是html5的新屬性,async 屬性規(guī)定一旦腳本可用,則會異步執(zhí)行(一旦下載完畢就會立刻執(zhí)行)。
需要注意的是async 屬性僅適用于外部腳本(只有在使用 src 屬性時)
defer屬性常常和async一起提起:
this is a test
似乎實(shí)現(xiàn)效果差不多,但是真的一樣嗎?我們來看看defer屬性的定義。
以前的defer只支持ie的hack,現(xiàn)在html5的出現(xiàn)開始全面支持defer。defer 屬性規(guī)定當(dāng)頁面已完成加載后,才會執(zhí)行腳本。defer 屬性僅適用于外部腳本(只有在使用 src 屬性時)。ps:ie支持的defer似乎并非如此,因?yàn)閷e無感,不深究,有興趣的可以去查閱相關(guān)資料。
既然async和defer經(jīng)常一起出現(xiàn),那么辨析一下吧!
如果沒有async和defer屬性(賦值為true,下同),那么瀏覽器會立即執(zhí)行當(dāng)前的js腳本,阻塞后面的腳本;如果有async屬性,加載和渲染后續(xù)文檔元素的過程將和當(dāng)前js的加載與執(zhí)行并行進(jìn)行(異步);如果有defer屬性,那么加載后續(xù)文檔元素的過程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素(DOM)解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。
來看一張網(wǎng)上盜的圖:
藍(lán)色線代表網(wǎng)絡(luò)讀取,紅色線代表執(zhí)行時間,這倆都是針對腳本的;綠色線代表 HTML 解析。
此圖告訴我們以下幾個要點(diǎn)(摘自defer和async的區(qū)別):
defer 和 async 在網(wǎng)絡(luò)讀?。ㄏ螺d)這塊兒是一樣的,都是異步的(相較于 HTML 解析)
它倆的差別在于腳本下載完之后何時執(zhí)行,顯然 defer 是最接近我們對于應(yīng)用腳本加載和執(zhí)行的要求的
關(guān)于 defer,此圖未盡之處在于它是按照加載順序執(zhí)行腳本的,這一點(diǎn)要善加利用
async 則是一個亂序執(zhí)行的主,反正對它來說腳本的加載和執(zhí)行是緊緊挨著的,所以不管你聲明的順序如何,只要它加載完了就會立刻執(zhí)行
仔細(xì)想想,async 對于應(yīng)用腳本的用處不大,因?yàn)樗耆豢紤]依賴(哪怕是最低級的順序執(zhí)行),不過它對于那些可以不依賴任何腳本或不被任何腳本依賴的腳本來說卻是非常合適的,最典型的例子:Google Analytics
但是在我看來(以下個人理解,如有出入還望指出),defer在異步加載上的應(yīng)用并不會比async廣。async的英文解釋是異步,該屬性作用在腳本上,使得腳本加載(下載)完后隨即開始執(zhí)行,和動態(tài)插入script標(biāo)簽作用類似(async只支持h6,后者能兼容瀏覽器);而defer的英文解釋是延遲,作用也和字面解釋類似,延遲腳本的執(zhí)行,使得dom元素加載完后才開始有序執(zhí)行腳本,因?yàn)橛行?,所以會帶來另一個問題:
this is a test console.log('hello world');
如果執(zhí)行這段代碼,控制臺的“hello world”也會遲遲得不到結(jié)果。所以我覺得還是async好用,如果要考慮依賴的話,可以選擇requirejs、seajs等模塊加載器。
感謝各位的閱讀!關(guān)于“處理JavaScript異步加載的注意事項(xiàng)有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
網(wǎng)頁標(biāo)題:?處理JavaScript異步加載的注意事項(xiàng)有哪些
分享路徑:http://weahome.cn/article/gsgepj.html