如何将<script src="https://remote.com/"></script>
元素注入我的页面,等待它执行,然后使用它定义的函数?
仅供参考:在我的情况下,脚本会在极少数情况下进行一些信用卡处理,所以我不想总是包含它。我想在用户打开更改信用卡选项对话框时快速包含它,然后向其发送新的信用卡选项。
编辑以获取更多详细信息:我无权访问远程脚本。
答案 0 :(得分:116)
您可以使用 Google Analytics 或 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方法;它依赖于现有的脚本标记而不是<head>
:
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)){ return; }
js = d.createElement(s); js.id = id;
js.onload = function(){
// remote script has loaded
};
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
facebook-jssdk
替换为您唯一的脚本标识符,以避免多次附加。{/ li>
答案 1 :(得分:29)
使用事件侦听器和ES2015构造的相同方法:
function injectScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.async = true;
script.src = src;
script.addEventListener('load', resolve);
script.addEventListener('error', () => reject('Error loading script.'));
script.addEventListener('abort', () => reject('Script loading aborted.'));
document.head.appendChild(script);
});
}
injectScript('http://example.com/script.js')
.then(() => {
console.log('Script loaded!');
}).catch(error => {
console.log(error);
});
答案 2 :(得分:9)
这是同步动态加载和执行脚本列表的一种方法。您需要将每个脚本标记插入DOM,并将其async属性显式设置为false:
script.async = false;
默认情况下,已经注入DOM的脚本是异步执行的,因此您必须手动将async属性设置为false以解决此问题。
<script>
(function() {
var scriptNames = [
"https://code.jquery.com/jquery.min.js",
"example.js"
];
for (var i = 0; i < scriptNames.length; i++) {
var script = document.createElement('script');
script.src = scriptNames[i];
script.async = false; // This is required for synchronous execution
document.head.appendChild(script);
}
// jquery.min.js and example.js will be run in order and synchronously
})();
</script>
<!-- Gotcha: these two script tags may still be run before `jquery.min.js`
and `example.js` -->
<script src="example2.js"></script>
<script>/* ... */<script>
答案 3 :(得分:6)
这样的事情应该可以解决问题:
(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/";
})();
希望有所帮助!欢呼声。
答案 4 :(得分:2)
import()
使用动态导入,您现在可以加载模块并等待它们执行,就像这样简单:
import("http://example.com/module.js").then(function(module) {
alert("module ready");
});
如果模块已经加载并执行,则不会再次加载并执行,但是import
返回的承诺仍然可以解决。
请注意,文件是作为模块而不是脚本加载的。模块以严格模式执行,并且在模块范围内加载,这意味着不会像在常规加载的脚本中那样自动将变量全局化。在模块中使用export
关键字可与其他模块或脚本共享变量。
答案 5 :(得分:0)
创建装载程序
您可以有序地将脚本注入到加载程序中。
请注意,动态加载脚本的执行通常是在静态加载脚本(即<script src="My_script.js"></script>
)之后执行的(DOM中的注入顺序并不能保证相反):
例如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
不能保证加载顺序。
答案 6 :(得分:0)
这是我根据弗兰克的回答改编的版本:
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;
});