动态加载时获取当前正在执行的js文件的url

2022-01-25 00:00:00 load include jquery javascript ajax

So I'm trying to load a script dynamically and figure out the URL path at which that script was loaded. So some guy gave me a pretty awesome solution to this problem if the scripts are statically loaded ( How to get the file-path of the currently executing javascript code ). But I need a dynamically loaded solution. For example:

$(function()
{   $.getScript("brilliant.js", function(data, textStatus)
    {   // do nothing   
    });
});

where "brilliant.js" has:

var scripts = document.getElementsByTagName("script");
var src = scripts[scripts.length-1].src;
alert("THIS IS: "+src);

Ideally this should either print out "brilliant.js" or "⟨hostname+basepath⟩/brilliant.js"

Currently brilliant.js works for statically included scripts, but not for scripts included dynamically (like with $.getScript). Anyone have any ideas? Is there somewhere in the dom that stores all the scripts that have been loaded?

EDIT: Andras gave a pretty good solution, though it probably only works for jQuery. Since that's probably the most popular library, and definitely what I'm going to be using. It can probably be extended for other libraries as well. Here's my simplified version:

var scriptUri;
curScriptUrl(function(x)
{   scriptUri = x;
    alert(scriptUri);
});

function curScriptUrl(callback)
{   var scripts = document.getElementsByTagName("script");
    var scriptURI = scripts[scripts.length-1].src;  

    if(scriptURI != "")         // static include
    {   callback(scriptURI);
    }else if($ != undefined)    // jQuery ajax
    {   $(document).ajaxSuccess(function(e, xhr, s)
        {   callback(s.url);
        }); 
    }
}

解决方案

When your script gets loaded with jQuery (and I guess other frameworks as well), your script will become indistinguishable from a script that was originally in the HTML document.

jQuery makes a request reaching out for your script and puts back the reply as the text child of a <script> node. Your browser has no way of knowing where it originated from, whether it was modified before inserted, etc. It is just a script node as far as she is concerned.

There can be workarounds, however. In the case of jQuery, you can hook up to the ajax events and exploit the fact that they are called right after your script executes. Basically, this would yield "brilliant.js" in your example:

var handler = function (e, xhr, s) {
    alert(s.url);
}

$(document).ajaxSuccess(handler);

A more elaborate one:

(function ($, undefined) {

    /* Let's try to figure out if we are inlined.*/
    var scripts = document.getElementsByTagName("script");

    if (scripts[scripts.length - 1].src.length === 0) {
        // Yes, we are inlined.
        // See if we have jQuery loading us with AJAX here. 
        if ($ !== undefined) {
            var initialized = false;
            var ajaxHandler = function (e, xhr, s) {
                if (!initialized) {
                    initialized = true;
                    alert("Inlined:" + s.url);
                    initmywholejsframework();
                }
            }

            //If it is, our handler will be called right after this file gets loaded.
            $(document).ajaxSuccess(ajaxHandler);

            //Make sure to remove our handler if we ever yield back.
            window.setTimeout(function () {
                jQuery(document).unbind("ajaxSuccess", ajaxHandler);
                if (!initialized) {
                    handleInlinedNonjQuery();
                }
            }, 0);

        }
    } else {
        //We are included.
        alert("Included:" + scripts[scripts.length - 1].src);
        initmywholejsframework();
    }

    //Handle other JS frameworks etc. here, if you will.
    function handleInlinedNonjQuery() {
        alert("nonJQuery");
        initmywholejsframework();
    }

    //Initialize your lib here
    function initmywholejsframework() {
        alert("loaded");
    }

})(jQuery);

相关文章