Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用远程src注入脚本标记并等待它执行_Javascript - Fatal编程技术网

Javascript 使用远程src注入脚本标记并等待它执行

Javascript 使用远程src注入脚本标记并等待它执行,javascript,Javascript,如何将元素注入页面,等待它执行,然后使用它定义的函数 仅供参考:在我的情况下,脚本将在极少数情况下执行一些信用卡处理,因此我不希望总是包含它。我想在用户打开“更改信用卡选项”对话框,然后向其发送新的信用卡选项时快速将其包括在内 编辑以获取更多详细信息:我没有访问远程脚本的权限。类似这样的操作应该可以: (function() { // Create a new script node var script = document.createElement("script");

如何将
元素注入页面,等待它执行,然后使用它定义的函数

仅供参考:在我的情况下,脚本将在极少数情况下执行一些信用卡处理,因此我不希望总是包含它。我想在用户打开“更改信用卡选项”对话框,然后向其发送新的信用卡选项时快速将其包括在内


编辑以获取更多详细信息:我没有访问远程脚本的权限。

类似这样的操作应该可以:

(function() {
    // Create a new script node
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.onload = function() {
        // Cleanup onload handler
        script.onload = null;

        // do stuff with the loaded script!

    }

    // Add the script to the DOM
    (document.getElementsByTagName( "head" )[ 0 ]).appendChild( script );

    // Set the `src` to begin transport
    script.src = "https://remote.com/";
})();

希望有帮助!干杯。

您可以使用谷歌分析Facebook的方法:

(function(d, script) {
    script = d.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.onload = function(){
        // remote script has loaded
    };
    script.src = 'http://www.google-analytics.com/ga.js';
    d.getElementsByTagName('head')[0].appendChild(script);
}(document));

更新:

下面是Facebook的新方法;它依赖于现有的脚本标记,而不是

  • facebook jssdk
    替换为您的唯一脚本标识符,以避免它被追加多次
  • 用您自己的url替换脚本的url

使用事件侦听器和ES2015构造的相同方法:

function injectScript(src) {
    return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;
        script.addEventListener('load', resolve);
        script.addEventListener('error', e => reject(e.error));
        document.head.appendChild(script);
    });
}

injectScript('https://example.com/script.js')
    .then(() => {
        console.log('Script loaded!');
    }).catch(error => {
        console.error(error);
    });

这是一种同步动态加载和执行脚本列表的方法。您需要将每个脚本标记插入DOM,并将其async属性显式设置为false:

script.async = false;
默认情况下,已注入DOM的脚本是异步执行的,因此必须手动将async属性设置为false才能解决此问题

例子

(功能(){
变量脚本名=[
"https://code.jquery.com/jquery.min.js",
“example.js”
];
对于(var i=0;i
工具书类
  • 谷歌的杰克·阿奇博尔德(Jake Archibald)写了一篇关于这个问题的文章,名为
  • 这是一个很好的和彻底的描述如何加载标签
动态
import()
使用动态导入,您现在可以加载模块并等待它们执行,如下所示:

import("http://example.com/module.js").then(function(module) {
  alert("module ready");
});
如果模块已经加载并执行,它将不会再次加载并执行,但是
import
返回的承诺仍将得到解决

请注意,文件是作为模块加载的,而不仅仅是作为脚本加载的。模块在严格模式下执行,并在模块范围内加载,这意味着变量不会像在正常加载的脚本中那样自动变为全局变量。在模块中使用
export
关键字与其他模块或脚本共享变量

参考资料:

创建加载程序

您可以在加载程序中以有序的方式注入脚本

请注意,动态加载脚本的执行通常在静态加载脚本(即
)之后进行(DOM中的注入顺序并不保证相反):

e、 g.,loader.js:

function appendScript(url){
   let script = document.createElement("script");
   script.src = url;
   script.async = false //IMPORTANT
   /*Node Insertion Point*/.appendChild(script);
}
appendScript("my_script1.js");
appendScript("my_script2.js");
my_script1.js
将在
my_script2.js
之前有效执行(如果
my_script2.js
的依赖项位于
my_script1.js
中,这将非常有用)


请注意,使用
script.async=false
非常重要,因为动态加载的脚本默认情况下具有
async=true
async
不能保证加载顺序。

以下是我根据Frank的回答改编的版本:

static async importScript(src, expressionToEvaluateAndReturn){

        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.async = true;
            script.src = src;
            script.addEventListener('load', (event)=>{
                if(expressionToEvaluateAndReturn){
                    try{
                        let result = eval(expressionToEvaluateAndReturn);
                        resolve(result);
                    } catch(error){
                        reject(error);
                    }

                } else {
                    resolve();
                }
            });
            script.addEventListener('error', () => reject('Error loading script "' + src + '"'));
            script.addEventListener('abort', () => reject('Script loading aborted for "' + src + '"'));
            document.head.appendChild(script);
        });    

    }   
用法示例:

let d3 = await importScript('/bower_components/d3/d3.min.js','d3')
                    .catch(error => {
                        console.log(error);
                        throw error;
                    });

您可以控制远程脚本吗?如果是这样的话,那么让脚本本身在完成时调用您的代码可能会更容易,a-la JSONPUNI幸运的是,我无法控制远程脚本。编辑问题以反映~这似乎很完美,但互联网上有一些传言称,并非所有浏览器都会调用onload。你知道这适用于哪些浏览器吗?为什么不将其附加到正文中?我不使用
script.onload
js.onload
,而是将事件侦听器添加到
load
事件中。附加到另一个
脚本
与附加到
相比,是否有好处?我看到附加到
脚本
s的缺点是,如果没有任何可附加到脚本的内容,则会中断。请注意,第一个查询
d.getElementsByTagName[0]
可以移动到
if
的下方,如果脚本已经存在,请检查以保存DOM查询。是否有理由在回调中将脚本onload手动设置为null?它多次触发是否有问题,或者这只是强制进行某种垃圾收集?是的,这是为了避免旧IE中的内存泄漏,因为脚本元素引用了一个函数作为onload处理程序。它现在正在工作,向上投票。顺便说一句,最后一个结束脚本缺少反斜杠。很好!这将是一个很好的NPM包或ES6模块+1的示例用法。你知道为什么在then()body中我不能使用加载的脚本中定义的变量/函数吗?@dar0x你检查过开发人员控制台吗?它可能会被网站的内容安全策略阻止。
static async importScript(src, expressionToEvaluateAndReturn){

        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.async = true;
            script.src = src;
            script.addEventListener('load', (event)=>{
                if(expressionToEvaluateAndReturn){
                    try{
                        let result = eval(expressionToEvaluateAndReturn);
                        resolve(result);
                    } catch(error){
                        reject(error);
                    }

                } else {
                    resolve();
                }
            });
            script.addEventListener('error', () => reject('Error loading script "' + src + '"'));
            script.addEventListener('abort', () => reject('Script loading aborted for "' + src + '"'));
            document.head.appendChild(script);
        });    

    }   
let d3 = await importScript('/bower_components/d3/d3.min.js','d3')
                    .catch(error => {
                        console.log(error);
                        throw error;
                    });