动态引入js只能生效一次_动态插入的script脚本执行时间
在一些場景我們會動態插入script標簽加載js。
譬如某個js文件不是很重要,并不是整個頁面需要的腳本,可能只是某個功能需要的,這個功能可能是用戶點擊了某個按鈕才觸發,入口比較深。且和你頁面本身的結構不同類,譬如你是基于react的頁面,這個功能的js是jquery插件。這種js文件我一般采用動態加載方式引入。
如果你用js動態插入script,那么它什么時候執行呢,如果插入多個script,且之間有依賴關系,是否先插入的script先執行呢?
答案是:不是
demo案例
js-exec.js:動態插入2個script到頁面中,test1.js中定義了一個全局變量obj,test2.js加載完成后的onload事件中會去使用這個變量obj。test1.js和test2.js都在打印了信息方便查看執行順序
var?getReadyForEditor?=?()?=>?{??console.log(obj.foo)
}
var?editorJs?=?document.createElement("script")
editorJs.src?=?"./test1.js"
document.body.appendChild(editorJs)
var?editorJs2?=?document.createElement("script")
editorJs2.src?=?"./test2.js"
editorJs2.onload?=?getReadyForEditor
document.body.appendChild(editorJs2)?
test1.js: 控制臺打印1,并且定義了obj變量
console.log(1)var?obj?=?{
??foo:?'foo'
}
test2.js: 控制臺打印2。
console.log(2)執行
通過不斷刷新,發現大概率是按照test1、test2的順序執行,但是也有一部分是先執行test2再執行test1:
由截圖可見,網絡請求順序是按照script插入的順序,先插入到dom的先請求,但是請求時間不一樣,test2比test1的請求時間短,內容先返回。看現象貌似結論是:資源加載完成時執行,因此資源加載先完成的先執行
猜測
我們都知道如果是非動態插入的script,是按照在html里出現的順序執行的,但是現在動態插入的腳本,雖然先插入的script位于html的前面,后插入的在后面,但是執行順序卻沒有按這個順序來。
是不是因為瀏覽器不知道在一個script標簽插入后還有沒有下一個要插入,所以沒法按順序執行呢?那么我們一次性插入這2個標簽會怎樣?
var?getReadyForEditor?=?()?=>?{??console.log(obj.foo)
}
var?editorJs?=?document.createElement("script")
editorJs.src?=?"./test1.js"
//?document.body.appendChild(editorJs)
var?editorJs2?=?document.createElement("script")
editorJs2.src?=?"./test2.js"
editorJs2.onload?=?getReadyForEditor
//?document.body.appendChild(editorJs2)?
var?docFrag?=?document.createDocumentFragment()
docFrag.appendChild(editorJs)?//?Note?that?this?does?NOT?go?to?the?DOM
docFrag.appendChild(editorJs2)
document.body.appendChild(docFrag)?
通過createDocumentFragment創造文檔片段,然后一次插入,這樣瀏覽器該知道順序了吧。
但是結果依舊沒變。猜想錯誤!
真相
MDN文檔:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
原來是因為瀏覽器對動態插入的script標簽,默認設置的是async。(各瀏覽器有區別)
我們知道async作用的js腳本時沒有順序的,異步加載,加載后執行。
因此特性,所以還有個defer,defer是異步加載,按script在文檔中的順序執行。
那我們的測試demo試一下,打印出來的async果真是true
如何讓動態插入的script標簽按插入順序執行
既然問題出在async上,那么創建script標簽時把他設置為false就好。
var?editorJs?=?document.createElement("script")editorJs.src?=?"./test1.js"
editorJs.async?=?false
document.body.appendChild(editorJs)
var?editorJs2?=?document.createElement("script")
editorJs2.src?=?"./test2.js"
editorJs2.onload?=?getReadyForEditor
editorJs2.async?=?false
document.body.appendChild(editorJs2)?
再觀察,即使test2比test1先加載完,也會等待test1執行完在執行了~
總結
以上是生活随笔為你收集整理的动态引入js只能生效一次_动态插入的script脚本执行时间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cuda-Block和Grid设定
- 下一篇: GPU资源分配