验证外部脚本是否已加载

AGo*_*ame 64 javascript asp.net jquery

我正在创建一个jquery插件,我想验证外部脚本是否已加载.这是一个内部Web应用程序,我可以保持脚本名称/位置一致(mysscript.js).这也是一个可以在页面上多次调用的ajaxy插件.

如果我可以验证脚本未加载,我将使用以下命令加载它:

jQuery.getScript()
Run Code Online (Sandbox Code Playgroud)

如何验证脚本是否已加载,因为我不希望多次在页面上加载相同的脚本?这是否因为缓存脚本而无需担心?

更新: 我可能无法控制谁在我们的组织中使用此插件,并且可能无法强制该脚本不在具有或不具有特定ID的页面上,但脚本名称将始终位于同一位置同名.我希望我可以使用脚本的名称来验证它实际上已加载.

Jas*_*per 129

如果脚本在全局空间中创建任何变量或函数,您可以检查它们是否存在:

外部JS(全球范围内) -

var myCustomFlag = true;
Run Code Online (Sandbox Code Playgroud)

并检查是否已运行:

if (typeof window.myCustomFlag == 'undefined') {
    //the flag was not found, so the code has not run
    $.getScript('<external JS>');
}
Run Code Online (Sandbox Code Playgroud)

更新

您可以<script>通过选择所有<script>元素并检查其src属性来检查相关标签的存在:

//get the number of `<script>` elements that have the correct `src` attribute
var len = $('script').filter(function () {
    return ($(this).attr('src') == '<external JS>');
}).length;

//if there are no scripts that match, the load it
if (len === 0) {
    $.getScript('<external JS>');
}
Run Code Online (Sandbox Code Playgroud)

或者您可以将此.filter()功能直接烘焙到选择器中:

var len = $('script[src="<external JS>"]').length;
Run Code Online (Sandbox Code Playgroud)

  • 脚本src检查没问题,但问题是脚本标记的存在与正确的src并不意味着加载了脚本.插入标记只是加载阶段的开始. (12认同)
  • 来自一个问题的@Jasper我假设通过将标记插入DOM来动态加载脚本.这是唯一一种可以多次插入相同脚本的情况(没有人在HTML中插入脚本,然后尝试动态再次加载它).因此,一旦插入脚本标记,您仍然要等到它被加载,在这种情况下,您的答案将无效,因为它只检查脚本标记是否存在. (3认同)

com*_*day 28

关于这个的答案很少,但我觉得值得添加这个解决方案。它结合了几个不同的答案。

对我来说关键点是

  • 添加#id标签,方便查找,不重复
  • 使用 .onload() 等待脚本加载完成后再使用

    mounted() {
      // First check if the script already exists on the dom
      // by searching for an id
      let id = 'googleMaps'
      if(document.getElementById(id) === null) {
        let script = document.createElement('script')
        script.setAttribute('src', 'https://maps.googleapis.com/maps/api/js?key=' + apiKey)
        script.setAttribute('id', id)
        document.body.appendChild(script) 
    
        // now wait for it to load...
        script.onload = () => {
            // script has loaded, you can now use it safely
            alert('thank me later')
            // ... do something with the newly loaded script
        }      
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • `script.onload` 是这里的正确答案。感谢分享! (3认同)
  • 像这样的答案就是为什么我不再相信已接受的答案......谢谢!`script.onload` 实际上会等待加载完成才采取行动,这正是我所需要的。 (2认同)

Abh*_*hek 11

@jasper的答案是完全正确的,但对于现代浏览器,标准的Javascript解决方案可能是:

function isScriptLoaded(src)
{
    return document.querySelector('script[src="' + src + '"]') ? true : false;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您愿意,您可以使用“布尔”而不是条件运算符 (3认同)

MyS*_*eam 7

创建具有特定 ID 的脚本标记,然后检查该 ID 是否存在?

或者,循环检查脚本“src”的脚本标签,并确保这些标签尚未加载与您想要避免的相同的值?

编辑:遵循代码示例有用的反馈:

(function(){
    var desiredSource = 'https://sitename.com/js/script.js';
    var scripts       = document.getElementsByTagName('script');
    var alreadyLoaded = false;

    if(scripts.length){
        for(var scriptIndex in scripts) {
            if(!alreadyLoaded && desiredSource === scripts[scriptIndex].src) {
                alreadyLoaded = true;
            }
        }
    }
    if(!alreadyLoaded){
        // Run your code in this block?
    }
})();
Run Code Online (Sandbox Code Playgroud)

正如评论中提到的(/sf/users/95114421/),这可能是另一种选择(未进行基准测试):

(function(){
    var desiredSource = 'https://sitename.com/js/script.js';
    var scripts = document.getElementsByTagName('script');
    var alreadyLoaded = false;

    for(var scriptIndex in document.scripts) {
        if(!alreadyLoaded && desiredSource === scripts[scriptIndex].src) {
            alreadyLoaded = true;
        }
    }
    if(!alreadyLoaded){
        // Run your code in this block?
    }
})();
Run Code Online (Sandbox Code Playgroud)


AGo*_*ame 7

这很简单,因为我已经意识到如何做到这一点,这要归功于引导我找到解决方案的所有答案.我不得不放弃$ .getScript()来指定脚本的来源...有时候手动操作是最好的.

//great suggestion @Jasper
var len = $('script[src*="Javascript/MyScript.js"]').length; 

if (len === 0) {
        alert('script not loaded');

        loadScript('Javascript/MyScript.js');

        if ($('script[src*="Javascript/MyScript.js"]').length === 0) {
            alert('still not loaded');
        }
        else {
            alert('loaded now');
        }
    }
    else {
        alert('script loaded');
    }


function loadScript(scriptLocationAndName) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = scriptLocationAndName;
    head.appendChild(script);
}
Run Code Online (Sandbox Code Playgroud)


Cyb*_*tic 5

只需检查全局变量是否可用,如果不可用则再次检查。为了防止超过最大调用堆栈,在检查时设置 100 毫秒超时:

function check_script_loaded(glob_var) {
    if(typeof(glob_var) !== 'undefined') {
    // do your thing
    } else {
    setTimeout(function() {
    check_script_loaded(glob_var)
    }, 100)
    }
}
Run Code Online (Sandbox Code Playgroud)