如何使用< script>按顺序将脚本插入到页面上下文中标签 [英] How to sequentially insert scripts into the page context using <script> tags

查看:151
本文介绍了如何使用< script>按顺序将脚本插入到页面上下文中标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有麻烦加载所有脚本,我从 content_script < script> 标签插入到页面上下文中c $ c>脚本,因为它们需要以正确的加载顺序执行,因为有些依赖于其他脚本。在一个实际的HTML文件中,我想有一个队列来加载文件,但插入< script> 标签似乎是一个脚本延迟了一段时间,下一个一个开始加载,然后立即执行,尽管它必须等待它的依赖库仍在加载。



以下是网络输出的错误,这是由于 x-tag-core.min.js 在使用 jquery-ui的 primeui-all.min.js eventPage.js 之前加载.min.js 在它之前加载:

  // manifest.js 
content_scripts:[
{
matches:[
< all_urls>
],
js:[
js / jquery-3.1.1.min.js,
js / main.js
]


code $ <$ $ p

  // 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);


解决方案

在代码段中复制问题



以下片段通过依次插入< script> 元素来重复您的问题。我正在使用网络资源,因为没有方法在Stack Overflow上存储这些脚本。鉴于你只提供jQuery的版本信息,我不得不猜测你正在使用的其他库的适当版本。



为了保持接近代码你在你的Chrome扩展中使用的是 chrome.extension.getURL()是伪造的。在这些片段中,该函数会为您正在使用的库返回一个功能性网络URL。显然,在您的Chrome扩展程序中,您会希望继续使用您的扩展程序中包含的库文件。

另外,<$ c $如果 $(document).puidialog 是一个函数,那么c> eventPage.js
会伪造成报告jQuery是否存在的代码,或者定义了 xtag 。您看到的错误是 $([something])。puidialog 不是函数, xtag 未定义。这个 fakeEventPageJS 代码准确地显示了脚本是否已被正确加载。



在这个问题的重复中,也是由各种库生成的,因为后续库无法找到之前的库。

truedata-console =truedata-babel =false>

  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'); //用实际script.s.textContent = fakeEventPageJS伪造js / eventPage.js; document.head .appendChild(s);  

<! - The包含在此HTML部分中的JavaScript代码用于伪造chrome API,并通过插入代码伪造js / eventPage.js文件的存在。 - > <! - 使用HTML<脚本>标签来测试在使用JavaScript插入测试之前通过这些作品加载它。如果您想验证脚本包含在原始HTML中时代码是否有效,您可以取消注释< script>标签在这里。 - ><! - 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 =stylesheethref =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 =stylesheethref =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分布/主/黄金elements.min.js>< /脚本> <! - - >< script> //假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]);返回netScriptLoations [脚本]; ;';'+'var passedChecks = 0;'+'if(typeof());} var fakeEventPageJS ='var testResult =脚本加载不正确。'+'+$(document).puidialog is not a function。 $ ===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 =脚本加载正确。'+'}'+'console.log(testResult);';< / script>



插入每个<脚本> onload 前面脚本的事件处理程序



很显然,插入的< script> 元素是异步执行的。为了强制它们同步执行,我们需要在前一个脚本完成执行之后插入下一个脚本。这可以通过利用 加载 $ b

以下代码加载 load 中的每个后续脚本

函数 createScriptElement 创建一个单独的< c>< ;脚本> 元素。由于不需要伪装 eventPage.js 脚本,因此该代码可以在代码中简化一些。



函数 createScriptSequence 创建一系列< script> 元素,每个元素都将下一个脚本插入 onload 监听器。这使用 script.addEventListerner('load',...)来避免被加载的脚本改变 script.onload property / attribute。



< /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']函数createScriptElement(script){let scriptEl = document.createElement('script');让scriptElSource = chrome.extension.getURL(script); if(scriptElSource){scriptEl.src = scriptElSource; } else {//只需要这个`else`是因为我们通过使用//一些代码来指示$(document).puidialog是否是函数来伪装js / eventPage.js。 scriptEl.textContent = fakeEventPageJS; } return scriptEl;} function createScriptSequence(scriptArray){var scriptEls = []; //创建所有的脚本元素scriptArray.forEach((script,index)=> {//console.log(script); scriptEls.push(createScriptElement(script)); if(index> 0){// Add a每个脚本的加载监听器(除了最后一个)加载//序列中的下一个scriptEls [index - 1] .addEventListener('load',function oneTime(){//可能不需要删除它,但更好的清理东西。scriptEls [index - 1] .removeEventListener('load',oneTime,false); document.head.appendChild(scriptEls [index]);},false);}}); //返回序列中的第一个脚本return scriptEls [0];} document.head.appendChild(createScriptSequence(scriptsToInsert));

 <! - 包含在此HTML部分中的JavaScript代码用于伪造chrome API,并伪造js / eventPage.js文件的存在通过插入代码。 - ><! -  jquery-ui.min.js  - >< link rel =stylesheethref =https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1 /themes/smoothness/jquery-ui.css\"> ;<!-- primeui-all.min.js  - >< link rel =stylesheethref =https://cdn.rawgit.com/ primefaces / primeui分布/主/ primeui-all.min.css><脚本> //假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]);返回netScriptLoations [脚本]; ;';'+'var passedChecks = 0;'+'if(typeof());} var fakeEventPageJS ='var testResult =脚本加载不正确。'+'+$(document).puidialog is not a function。 $ ===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 =脚本加载正确。'+'}'+'console.log(testResult);';< / 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.

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);

解决方案

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.

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.

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>

Insert each <script> in the onload event handler of the prior script

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.

The following code loads each subsequent script in the load event handler of the prior script.

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.

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>

这篇关于如何使用&lt; script&gt;按顺序将脚本插入到页面上下文中标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆