JavaScript loading issues

I have one JS file in the header (this is for Google DFP) and the other before </body>

I found that if the JS header file does not load to the bottom, I get this error in the Chrome console:

  Uncaught TypeError: Object #<Object> has no method 'defineSlot' 

The defining value is defined in the first script. This problem occurs only in every 10-page update, so most of the time it works fine.

I want to advise how to deal with this problem. The following are two scenarios:

Script Header:

 <script type='text/javascript'> var googletag = googletag || {}; googletag.cmd = googletag.cmd || []; (function() { var gads = document.createElement('script'); gads.async = true; gads.type = 'text/javascript'; var useSSL = 'https:' == document.location.protocol; gads.src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js'; var node = document.getElementsByTagName('script')[0]; node.parentNode.insertBefore(gads, node); })(); </script> <script type='text/javascript'> googletag.cmd.push(function() { googletag.pubads().enableAsyncRendering(); slot1 = googletag.defineSlot('/21848415/GoneGlobal_Square', [250, 250], 'doubleClickSquareIndex-250-250').addService(googletag.pubads()); slot2 = googletag.defineSlot('/21848415/GoneGlobal_Skyscraper', [160, 600], 'doubleClickSkyscraperIndex-160-600').addService(googletag.pubads()); slot3 = googletag.defineSlot('/21848415/GoneGlobal_Leaderboard', [728, 90], 'doubleClickLeaderboardIndex-728-90').addService(googletag.pubads()); slot4 = googletag.defineSlot('/21848415/GoneGlobal_Leaderboard', [728, 90], 'doubleClickLeaderboardHeaderInternal-728-90').addService(googletag.pubads()); slot5 = googletag.defineSlot('/21848415/GoneGlobal_SmallSquare', [200, 200], 'doubleClickSmallSquareHeaderExternal-200-200').addService(googletag.pubads()); googletag.enableServices(); }); </script> 

Below the second script is only part of it (rather long):

 $(function() { ///////////////////////// Double Click AD Variables var slot1 = googletag.defineSlot('/21848415/GoneGlobal_Square', [250, 250], 'doubleClickSquareIndex-250-250'); var slot2 = googletag.defineSlot('/21848415/GoneGlobal_Skyscraper', [160, 600], 'doubleClickSkyscraperIndex-160-600'); var slot3 = googletag.defineSlot('/21848415/GoneGlobal_Leaderboard', [728, 90], 'doubleClickLeaderboardIndex-728-90'); var slot4 = googletag.defineSlot('/21848415/GoneGlobal_Leaderboard', [728, 90], 'doubleClickLeaderboardHeaderInternal-728-90'); var slot5 = googletag.defineSlot('/21848415/GoneGlobal_SmallSquare', [200, 200], 'doubleClickSmallSquareHeaderExternal-200-200'); )}; 

Is there a way to stop the script from starting another other method / function?

Is it possible to create some kind of addiction?

How can I ensure that the top js is loaded to the bottom?

+4
source share
3 answers

Keep your scripts in separate files. Then the following should work:

 function loadScript(pathToScript, callback) { var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.type = "text/javascript"; script.src = pathToScript + "?t=" + new Date().getTime(); //prevent caching if (callback) { script.onload = callback; } head.appendChild(script); } 

The loadScript function loads a script that is on "pathToScript", and once it has finished loading the script, it calls the provided callback. You need a callback because loading an external resource is an asynchronous operation. This means that you basically need a โ€œnotificationโ€ when it has finished loading an external resource. This is basically what the callback does. If you are dependent on data coming from an asynchronous operation, you cannot disable this operation, and then continue working and try to use the data or resource because the data will not have a completed download. That way, any code that depends on the resource you put inside the callback. Why we do this will be clearer later.

 var scripts = ["/path/to/first/script.js", "/path/to/second/script.js"]; function load(i) { if (i < scripts.length) { loadScript(scripts[i], function () { load(++i); }); } else { //all your scripts have loaded, so go ahead and do what you need to do } } load(0); 

The scripts array contains an array of loaded scripts. The order is implied by the position of the script in the array. This way, the script that is in scripts[0] will be loaded before the script in scripts[1] .

The load function ensures that you load your scripts in the desired order. We know that the load operation is asynchronous. We also know that after the operation is completed, a callback will be called. Using this information, we can load the second script after the script has finished loading. There is one argument load , which represents the current index of the scripts array. First we set the index i to 0 , which means that we will first load the script at index 0 . Then we look at the value of i . If it is less than the length of the array, this means that we have not completed all the scripts (think of it as a loop). Therefore, if i less than the length, we call the loadScript function with the value scripts[i] . Then in our callback we call our load function again, but this time we increase the current value of i . Therefore, when the script has finished loading, we end up calling load with an index with the extension, and now we can load our next script.

If i is equal to scripts.length , this means that we have loaded all our scripts, and therefore we will go to the else block, and this is where you put the code that you need to run at the end of the scripts loaded.

The last line is the actual load call with argument 0 , which starts the whole process, starting from the path to the first script, which is located at index 0 scripts array.

You can rewrite the load function as IIFE if you want:

 (function load(i) { if (i < resources.length) { loadResource(resources[i], function () { load(++i); }); } })(0); 

Here you have a self-invoked function that calls itself in a callback. It is functionally equivalent to the less exotic version above.

+4
source

Other solutions here may work, but the real problem is how you use DFP.

DFP loads asynchronously, so the defineSlot method will not exist on your page during the execution of the script that causes the error.

All of your DFP code must be contained in the googletag.cmd.push shell, which will store the commands until DFP is loaded and then executes them in the correct order.

Just wrap any such DFP code to fix the errors:

 googletag.cmd.push(function() { // Double Click AD Variables }); 
+5
source

you can create your own event, say first_script_loaded , and when the first script is loaded, you can add $(document).trigger("first_script_loaded") at the end, you can also set a global boolean just for that, where it is set at the beginning of false , and when the 1st script loads, you set it to true

in the second script, check if boolean true , which means that the first script is already loaded before the second script starts loading, but if it is false, to the $(document).on("first_script_loaded") and add your code to the callback method on .

0
source

All Articles