getScript - How to only call if not already called
on a Click, the followi开发者_开发百科ng gets loaded:
$.getScript('/javascripts/contacts.js');
How can I write a statement that says
if the getScript above is already loaded do X,, if not loaded it, do Y...?
Thanks
var gotContacts = 0;
function getContacts(){
if (!gotContacts){
$.getScript('/javascripts/contacts.js', function() {
gotContacts = 1;
doSomethingWithContacts();
});
}else{
doSomethingWithContacts();
}
}
My situation was different. I used a menu to load content into a div using jquery. To prevent too many scripts from being present in the header section, I used .getscript to load the file only if that link was called. Here is the solution I came up with to prevent duplicates:
First I create a function that was responsible for loading the script. This is part of the global.js file on my site and the global.js file is hard coded into the header:
var loadedScripts=new Array();
function loadScriptFiles(scriptArray){
if($.isArray(scriptArray)){
$.each(scriptArray, function(intIndex, objValue){
if($.inArray(objValue, loadedScripts) < 0){
$.getScript(objValue, function(){
loadedScripts.push(objValue);
});
}
});
}
else{
if($.inArray(script, loadedScripts) < 0){
$.getScript(script, function(){
loadedScripts.push(objValue);
});
}
}
}
This takes two types of loads, either an array, or a single script value. If it's an array, it loops through each element and loads it. If it's not an array, then it'll just load one file. You'll see that part in a minute.
Important parts: See I've created an array in the global scope (outside of the function) called loadedScripts. Because this is part of the global.js file, it never gets reloaded and can be called from anywhere. But for our purposes, I simply check to see if the script name being loaded is already in the array using:
if($.inArray(objValue, loadedScripts) < 0){
Because the jquery inarray function returns -1 if the value is not found, I only continue if the value is less than 0. Anything else means the value is in the array.
Here is how you call the function to be used. Place this code anywhere (I put it at the top) of the dynamic page that will be called into play.
<script type="text/javascript">
var scriptArray=new Array();
scriptArray[0]="[REPLACE THIS WITH THE PATH TO THE JS FILE]";
scriptArray[1]="[REPLACE THIS WITH THE PATH TO THE JS FILE]";
loadScriptFiles(scriptArray);
</script>
If done properly, you'll notice it only gets loaded once.
I've created a plugin that does almost exactly what you want: $.getScriptOnce()
.
If you try to load the same script twice or more it will not load the script and return false.
But basically, it defines this alternative function of $.getScript()
(function($) {
$.getScriptOnce = function(url, successhandler) {
if ($.getScriptOnce.loaded.indexOf(url) === -1) {
$.getScriptOnce.loaded.push(url);
if (successhandler === undefined) {
return $.getScript(url);
} else {
return $.getScript(url, function(script, textStatus, jqXHR) {
successhandler(script, textStatus, jqXHR);
});
}
} else {
return false;
}
};
$.getScriptOnce.loaded = [];
}(jQuery));
And then simply call $.getScriptOnce('yourFile.js')
Use require.js
$.getScript( "https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js")
.done(function () {
alert('is called');
})
`.fail(function () {
alert('is not called');
});
Since $.getScript()
return promise
interface, you can do something like this:
$.getScriptOnce = (function() {
var cache = {};
return function(url, success) {
if (!cache[url]) {
cache[url] = $.getScript(url, success);
} else if($.isFunction(success)) {
cache[url].done(success);
}
return cache[url];
}
})();
// Script will be loaded and executed once.
// All callbacks will be executed on success.
$.getScriptOnce('hello.js', function(data), {
alert('callback 1');
});
$.getScriptOnce('hello.js', function(data), {
alert('callback 2');
});
$.getScriptOnce('hello.js');
$.getScriptOnce('hello.js').done(function() {
alert('loaded');
}).error(function() {
alert('error');
});
hello.js
alert('Hello from hello.js');
I also wrote such function. You can test with the Network tab in Firebug or Chrome dev tools. This just loads the same file once.
Pay attention not to download the second time immediately after the previous, because the function just assumes the file was loaded, after the callback is called, i.e., after the file was loaded successfully.
var getScriptOnce = (function(url, callback) {
var scriptArray = []; //array of urls
return function (url, callback) {
//the global array doesn't have such url
if (scriptArray.indexOf(url) === -1){
if (typeof callback === 'function') {
return $.getScript(url, function(script, textStatus, jqXHR) {
scriptArray.push(url);
callback(script, textStatus, jqXHR);
});
} else {
return $.getScript(url, function(){
scriptArray.push(url);
});
}
}
//the file is already there, it does nothing
//to support as of jQuery 1.5 methods .done().fail()
else{
return {
done: function () {
return {
fail: function () {}
};
}
};
}
}
}());
/*#####################################################################*/
/*#####################################################################*/
//TEST - tries to load the same jQuery file twice
var jQueryURL = "https://code.jquery.com/jquery-3.2.1.js";
console.log("Tries to load #1");
getScriptOnce(jQueryURL, function(){
console.log("Loaded successfully #1")
});
//waits 2 seconds and tries to load again
window.setTimeout(function(){
console.log("Tries to load #2");
getScriptOnce(jQueryURL, function(){
console.log("Loaded successfully #2");
});
}, 2000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Don't do this; don't treat the <script>
tag as your compiler loading your source code. Instead, concatenate all your source code together using a javascript minifier, and only hit the server once.
Loading one 4k file is better than loading four 1k files, and the minifier can probably do a better job than that. You shouldn't need it anyway- your browser is caching these modules anyway and unless you mess up your server config, it will do the right thing.
If you really want to continue, first look at demand-loading javascript libraries like Ensure, or Ajile or Dojo, or JSAN. At least then, you're not reinventing the wheel.
Still want to do it yourself? You can either check for something that contacts.js
does, or use a variable to test whether you've done it. If contacts.js
has something like this in it:
function ContactsLoaded(){...}
You can do:
if(typeof ContactsLoaded=='undefined')$.getScript('contacts.js');
Alternatively, you can set it yourself and make a loader function:
function getScriptOnce(f){
var a=getScriptOnce;
if(typeof a[f]=='undefined')$.getScript(f);
a[f]=true;
}
精彩评论