如何使用 <script> 将脚本顺序插入到页面上下文中标签 [英] How to sequentially insert scripts into the page context using <script> tags
问题描述
我在使用 <script>
标签从 content_script
脚本加载我插入到页面上下文中的所有脚本时遇到问题,因为它们必须是以正确的加载顺序执行,因为有些依赖于其他.在一个实际的 HTML 文件中,我猜有一个队列来加载文件,但是通过插入 <script>
标签,如果一个脚本延迟一点时间,下一个脚本开始加载然后是立即执行,尽管它必须等待仍在加载的依赖库.
I am having troubles loading all the scripts that I am inserting into the page context with <script>
tags from a content_script
script, because they are required to be executed in the correct loading order, as some depend on others. In an actual HTML file I guess there is a queue to load the files, but with inserting <script>
tags it seems like if one script delays a little time, the next one starts loading and then is immediately executed notwithstanding it had to wait for its dependency library that is still loading.
下面是由于x-tag-core.min.js在primeui-all.min.js和之前加载导致错误的网络输出>eventPage.js 使用 jquery-ui.min.js,在它之前加载:
Below is the network output with the error caused because of x-tag-core.min.js is loaded before primeui-all.min.js and eventPage.js which uses jquery-ui.min.js, is loaded before it:
// manifest.js
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"js/jquery-3.1.1.min.js",
"js/main.js"
]
}
]
// main.js
var s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-3.1.1.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-ui.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeui-all.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/x-tag-core.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeelements.min.js');
$(document.head).append(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/eventPage.js');
$(document.head).append(s);
推荐答案
在片段中复制您的问题
以下代码段通过依次插入 元素来重复您的问题.我正在使用网络资源,因为没有在 Stack Overflow 上存储此类脚本的方法.鉴于您只提供了 jQuery 的版本信息,我不得不猜测您正在使用的其他库的适当版本.
Duplicating your problem in a snippet
The following snippet duplicates your problem by sequentially inserting <script>
elements. I am using network resources, because there is no method of storing such scripts on Stack Overflow. Given that you only supplied version information for jQuery, I have had to guess at appropriate versions for the other libraries which you are using.
为了接近您在 Chrome 扩展程序中使用的代码,chrome.extension.getURL()
是伪造的.在这些片段中,该函数返回您正在使用的库的功能网络 URL.显然,在您的 Chrome 扩展程序中,您将希望继续使用扩展程序中包含的库文件.
In order to stay close to the code which you are using in your Chrome extension, chrome.extension.getURL()
is faked. In these snippets, that function returns a functional network URL for the libraries which you are using. Obviously, in your Chrome extension, you will want to continue to use the library files which you ave included with your extension.
另外,eventPage.js
的代码是伪造的,有一些代码会报告 jQuery 是否存在,如果 $(document).puidialog
是一个函数,并且/或如果 xtag
已定义.您看到的错误是 $([something]).puidialog
不是函数,并且 xtag
未定义.此 fakeEventPageJS
代码准确地显示了脚本是否已正确加载.
In addition, the code for eventPage.js
is faked by having some code that reports if jQuery exists, if $(document).puidialog
is a function, and/or if xtag
is defined. The errors you are seeing are that $([something]).puidialog
was not a function and xtag
was not defined. This fakeEventPageJS
code accurately shows if the scripts have been properly loaded.
在这个重复的问题中,由于后续的库无法找到先前的库,因此各个库也会产生错误.
In this duplication of your problem, an error is also produced from the various libraries as the subsequent libraries can not find prior libraries.
var s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-3.1.1.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/jquery-ui.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeui-all.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/x-tag-core.min.js');
document.head.appendChild(s);
s = document.createElement('script');
s.src = chrome.extension.getURL('js/primeelements.min.js');
document.head.appendChild(s);
s = document.createElement('script');
//s.src = chrome.extension.getURL('js/eventPage.js');
//Fake js/eventPage.js with an actual script.
s.textContent = fakeEventPageJS;
document.head.appendChild(s);
<!-- The JavaScript code included in this HTML section is used to fake the chrome API
and part of faking the existence of a js/eventPage.js file by inserting code. -->
<!-- Using HTML <script> tags to test that loading it via these works prior to testing
using JavaScript inserts. If you want to verify that the code works when the
scripts are included in the original HTML, you can uncomment the <script>
tags here. -->
<!-- jquery-3.1.1.min.js -->
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script><!-- -->
<!-- jquery-ui.min.js -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script><!-- -->
<!-- primeui-all.min.js -->
<link rel="stylesheet" href="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.css">
<!-- <script src="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.js"></script><!-- -->
<!-- x-tag-core.min.js -->
<!-- <script src="https://cdn.rawgit.com/x-tag/core/master/dist/x-tag-core.min.js"></script>
<!-- primeelements.min.js -->
<!-- <script src="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeelements.min.js"></script> <!-- -->
<script>
//Fake chrome.extension.getURL
var netScriptLoations = {
'js/jquery-3.1.1.min.js':'https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js',
'js/jquery-ui.min.js':'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js',
'js/primeui-all.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.js',
'js/x-tag-core.min.js':'https://cdn.rawgit.com/x-tag/core/master/dist/x-tag-core.min.js',
'js/primeelements.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeelements.min.js'
}
if(typeof chrome !== 'object'){
var chrome = {};
}
if(typeof chrome.extension !== 'object'){
chrome.extension = {};
}
if(typeof chrome.extension.getURL !== 'function'){
chrome.extension.getURL = function(script){
//console.log(netScriptLoations[script]);
return netScriptLoations[script];
};
}
var fakeEventPageJS =
'var testResult = "Scripts did NOT load correctly. "'
+ ' + "$(document).puidialog is NOT a function.";'
+ 'var passedChecks=0;'
+ 'if(typeof $ === "function"){'
+ ' var puidialogNot = " NOT";'
+ ' if(typeof $(document).puidialog === "function") {'
+ ' puidialogNot = "";'
+ ' }'
+ ' console.log("$(document).puidialog is" + puidialogNot + " a function");'
+ '} else {'
+ ' console.log("No jQuery");'
+ '}'
+ 'var xtagNot = " NOT";'
+ 'if(typeof xtag !== "undefined") {'
+ ' xtagNot = "";'
+ '}'
+ 'console.log("xtag is" + xtagNot + " defined.");'
+ 'if(puidialogNot + xtagNot === "") {'
+ ' testResult = "Scripts loaded CORRECTLY. "'
+ '}'
+ 'console.log(testResult);';
</script>
很明显,插入的元素是异步执行的.为了强制它们同步执行,我们需要在前一个脚本执行完成后插入下一个脚本.这可以通过使用
load
事件来完成 对于每个脚本.
It is clear that the inserted <script>
elements are executed asynchronously. In order to force them to be executed synchronously, we need to insert the next script after the prior one has completed execution. This can be done by utilizing the load
event for each script.
以下代码在前一个脚本的 load
事件处理程序中加载每个后续脚本.
The following code loads each subsequent script in the load
event handler of the prior script.
函数 createScriptElement
创建一个单独的 元素.由于不需要伪造 eventPage.js 脚本,因此可以在代码中稍微简化此函数.
The function createScriptElement
creates an individual <script>
element. This function can be somewhat simplified in your code due to not needing to fake the eventPage.js script.
函数 createScriptSequence
创建一系列 元素,每个元素将下一个脚本插入到其
onload
侦听器中.这使用 script.addEventListerner('load',...)
以免受正在加载的脚本更改 script.onload
属性/属性的影响.
The function createScriptSequence
creates a sequence of <script>
elements which each inserts the next script in its onload
listener. This uses script.addEventListerner('load',...)
in order to be immune to the script being loaded changing the script.onload
property/attribute.
var scriptsToInsert = [
'js/jquery-3.1.1.min.js',
'js/jquery-ui.min.js',
'js/primeui-all.min.js',
'js/x-tag-core.min.js',
'js/primeelements.min.js',
'js/eventPage.js'
]
function createScriptElement(script){
let scriptEl = document.createElement('script');
let scriptElSource = chrome.extension.getURL(script);
if(scriptElSource){
scriptEl.src = scriptElSource;
} else {
//Only need this `else` because we are faking having js/eventPage.js by using
// some code to indicate if $(document).puidialog is a function.
scriptEl.textContent = fakeEventPageJS;
}
return scriptEl;
}
function createScriptSequence(scriptArray){
var scriptEls = [];
//Create all the script elements
scriptArray.forEach((script,index)=>{
//console.log(script);
scriptEls.push(createScriptElement(script));
if(index>0){
//Add an onload listener for each script (except the last) which loads
// the next one in the sequence.
scriptEls[index - 1].addEventListener('load',function oneTime(){
//Probably don't need to remove this, but better to clean things up.
scriptEls[index - 1].removeEventListener('load',oneTime,false);
document.head.appendChild(scriptEls[index]);
},false);
}
});
//Return the first script in the sequence
return scriptEls[0];
}
document.head.appendChild(createScriptSequence(scriptsToInsert));
<!-- The JavaScript code included in this HTML section is used to fake the chrome API
and part of faking the existence of a js/eventPage.js file by inserting code. -->
<!-- jquery-ui.min.js -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<!-- primeui-all.min.js -->
<link rel="stylesheet" href="https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.css">
<script>
//Fake chrome.extension.getURL
var netScriptLoations = {
'js/jquery-3.1.1.min.js':'https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js',
'js/jquery-ui.min.js':'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js',
'js/primeui-all.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeui-all.min.js',
'js/x-tag-core.min.js':'https://cdn.rawgit.com/x-tag/core/master/dist/x-tag-core.min.js',
'js/primeelements.min.js':'https://cdn.rawgit.com/primefaces/primeui-distribution/master/primeelements.min.js'
}
if(typeof chrome !== 'object'){
var chrome = {};
}
if(typeof chrome.extension !== 'object'){
chrome.extension = {};
}
if(typeof chrome.extension.getURL !== 'function'){
chrome.extension.getURL = function(script){
//console.log(netScriptLoations[script]);
return netScriptLoations[script];
};
}
var fakeEventPageJS =
'var testResult = "Scripts did NOT load correctly. "'
+ ' + "$(document).puidialog is NOT a function.";'
+ 'var passedChecks=0;'
+ 'if(typeof $ === "function"){'
+ ' var puidialogNot = " NOT";'
+ ' if(typeof $(document).puidialog === "function") {'
+ ' puidialogNot = "";'
+ ' }'
+ ' console.log("$(document).puidialog is" + puidialogNot + " a function");'
+ '} else {'
+ ' console.log("No jQuery");'
+ '}'
+ 'var xtagNot = " NOT";'
+ 'if(typeof xtag !== "undefined") {'
+ ' xtagNot = "";'
+ '}'
+ 'console.log("xtag is" + xtagNot + " defined.");'
+ 'if(puidialogNot + xtagNot === "") {'
+ ' testResult = "Scripts loaded CORRECTLY. "'
+ '}'
+ 'console.log(testResult);';
</script>
这篇关于如何使用 <script> 将脚本顺序插入到页面上下文中标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!