Javascript 仅在尚未加载时加载 js 脚本,然后仅加载一次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26331600/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Load js script only when it has not been loaded already and then only once
提问by wordSmith
I've been trying to load a big js script only once. I'm not loading it on page load as it is not needed then and will slow the page load down.
我一直在尝试只加载一次大型 js 脚本。我不会在页面加载时加载它,因为那时不需要它并且会减慢页面加载速度。
So I've been trying to load it with jQuery's $.getScript and Modernizr.load ( since I'm already using Modernizr ).
所以我一直在尝试使用 jQuery 的 $.getScript 和 Modernizr.load 加载它(因为我已经在使用 Modernizr )。
I've tried iterating through all the <script></script>elements and checking their src attributes and seeing if this script is one of them, but that still loaded them each time I ran the test.
我已经尝试遍历所有<script></script>元素并检查它们的 src 属性并查看此脚本是否是其中之一,但是每次运行测试时仍然加载它们。
I also tried setting a global variable to true at the beginning of the script and checking if that was set and it still loaded every time I checked. Here is what I was doing in that instance:
我还尝试在脚本的开头将全局变量设置为 true 并检查是否已设置并且每次检查时它仍然加载。这是我在那个例子中所做的:
Modernizr.load({
test:if(window.flag === undefined),
yep:'conversation.js',
callback:function(){
antecedent();
}
});
and var flag = true;was set at the first line of conversation.js
并var flag = true;设置在conversation.js的第一行
Does anyone have any ideas how I can get this script to load once when this test is called to check if it is has been loaded and only load it once then?
有没有人知道如何在调用此测试以检查它是否已加载时加载此脚本一次,然后只加载一次?
** Edit/Update: ** document.getElementsByTagName('head')[0].appendChild(document.createElement('sc??ript')).src = 'conversation.js';could work, but how do I check if the script is already loaded or not and then only call this if it isn't already included?
** 编辑/更新:**document.getElementsByTagName('head')[0].appendChild(document.createElement('sc??ript')).src = 'conversation.js';可以工作,但如何检查脚本是否已加载,然后仅在尚未包含的情况下调用它?
回答by Jared Smith
First, you'll need to check if the script is already on the page:
首先,您需要检查脚本是否已经在页面上:
var list = document.getElementsByTagName('script');
var i = list.length, flag = false;
while (i--) {
if (list[i].src === 'filePathToJSScript') {
flag = true;
break;
}
}
// if we didn't already find it on the page, add it
if (!flag) {
var tag = document.createElement('script');
tag.src = 'filePathToJSScript';
document.getElementsByTagName('body')[0].appendChild(tag);
}
The code in the conditional can be used to dynamically add scripts to the page.
条件中的代码可用于向页面动态添加脚本。
ES 6 Update
ES 6 更新
ES 6 simplifies this quite a bit:
ES 6 大大简化了这一点:
let scripts = Array
.from(document.querySelectorAll('script'))
.map(scr => scr.src);
if (!scripts.includes('filePathToJSScript')) {
// same as above
}
回答by Wayne
Life is easier if you insure the script is loaded only once in the source code. If php is being used to load scripts let it also handle the dependencies.
如果您确保脚本在源代码中只加载一次,生活会更轻松。如果 php 被用于加载脚本,让它也处理依赖项。
Functions are first class objects and if a object does not exist it converts to a Boolean false in if statement.
函数是第一类对象,如果对象不存在,它会在 if 语句中转换为布尔值 false。
if (myFunction) { /* myFunction exists in myscript */
} else {
var myScript = document.createElement('script');
document.getElementById("main").appendChild(myScript);
myScript.src = "http://example/myscript.js";
}
However, this causes the script to be loaded asynchronously. Using document.write may still load asynchronously. Meaning a call can be made to the script elsewhere before the script is loaded. You may also need to program a promise maker and promise keeper to handle these calls, Not impossible but ... onload used to make promise, if it does not load my promise was broken.
但是,这会导致脚本异步加载。使用 document.write 可能仍会异步加载。这意味着可以在加载脚本之前在其他地方调用脚本。你可能还需要编写一个promise maker和promise keeper来处理这些调用,这不是不可能的,但是……onload用来做promise,如果它不加载我的promise就被破坏了。
if (myFunction) {
/* Call the function I needed no promise needed. */
myFunction();
} else { /* myFunction exists in myscript */
var myScript = document.createElement('script');
document.getElementById("main").appendChild(myjsonp);
myScript.onload = "/* promise fulfillment */"
myScript.src = "http://example/myscript.js";
}
All of this coding may end of removing any benefit of not having it loaded on every page, regardless if it is used, an letting it be a cached asset across the site.
所有这些编码可能会消除不将其加载到每个页面上的任何好处,无论是否使用它,让它成为整个站点的缓存资产。
Note onload for scripts is only HTML5.
注意脚本的 onload 只是 HTML5。
myscript.js however can have the promise keeper. It can look for a global which is a array of promises, and if that array exists run the promises.
然而,myscript.js 可以拥有承诺守护者。它可以寻找一个全局的承诺数组,如果该数组存在,则运行承诺。
If myscript.js is loaded with jquery ajax, the promise keeper can be contained with the done function.
如果 myscript.js 是用 jquery ajax 加载的,promise keeper 可以包含在 done 函数中。
回答by guest271314
Note, return value of console.log(Modernizr.hasOwnProperty("load"))? . See http://github.com/SlexAxton/yepnope.js#deprecation-notice
注意,返回值console.log(Modernizr.hasOwnProperty("load"))? . 见http://github.com/SlexAxton/yepnope.js#deprecation-notice
"For these reasons, we're also not going to include yepnope in the next version of Modernizr as Modernizr.load."
“出于这些原因,我们也不打算在 Modernizr 的下一个版本中将 yepnope 包含为 Modernizr.load。”
Try
尝试
$(function() {
var callbacks = $.Callbacks("once");
callbacks.add(
$.getScript("conversation.js", function(data, textStatus) {
console.log(textStatus, window.flag)
})
);
if (window.flag === undefined) {
callbacks.fire()
} else {
console.log(window.flag)
}
})
回答by Alexander Craggs
A simpler solution (again assuming ES6) would be:
一个更简单的解决方案(再次假设 ES6)是:
function load_script(url) {
if (!Array.from(document.querySelectorAll('script')).some(elm => elm.src == url)) {
let script = document.createElement('script')
script.src = url
document.getElementsByTagName('head')[0].appendChild(script)
}
}
The .some()function will return true if any of the elements contain a src that is the URL, allowing you to then add the element to the end of the <head>part of the script.
.some()如果任何元素包含作为 URL 的 src,则该函数将返回 true,然后允许您将该元素添加到<head>脚本部分的末尾。

