很久沒有遇到這問題了,如果有需要動態 inject 外部的 js 到你的 html 裡面,而且又需要使用外部的 js 的 function 時,該怎麼做才能確保在 js load 完之後,才能夠執行外部 js 的 function 呢?
起因
這算是蠻容易遇到的問題,常常會認為在動態載入 javascript 之後,就可以直接使用它,像是下面的例子:
外部的 https://www.eample.com/test.js
:
1 2 3
| var test = () => { console.log('i am test'); };
|
你打算動態的載入這 js,並執行它:
test.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script> // dynamic load js (function(d, id) {
if (d.getElementById(id)) { return; }
let fjs = d.getElementsByTagName('script')[0]; let js = d.createElement('script');
js.id = id; js.src = "https://www.eample.com/test.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'testId'));
//execute external js test(); </script>
|
會發現到有時候 https://www.eample.com/test.js
的 test()
有時候可以執行,有時候不行,如果網路速度過慢的話,還會以為完全不能執行。
原因就出在於瀏覽器載入 test.js
的時候可能還沒完成,就已經先執行 test()
。
解決方式
所以要使用 script 的 onload event
確保在 test.js
載入完畢後才能執行 function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <script> let scriptOnload = () => { //execute external js test(); };
// dynamic load js (function (d, id, callBack) {
if (d.getElementById(id)) { return; }
let fjs = d.getElementsByTagName('script')[0]; let js = d.createElement('script');
js.id = id; js.onload = callBack; js.src = "https://www.eample.com/test.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'testId', scriptOnload)); </script>
|