JavaScript加载顺序导致问题 [英] JavaScript loading order causing issues

查看:90
本文介绍了JavaScript加载顺序导致问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在标头中有一个JS文件(这是针对Google DFP的),在</body>

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

我发现头JS文件是否在最底端的JS文件之前没有加载,我在Chrome控制台中收到此错误:

I have found if the header JS file doesn't load before the bottom one I get this error in Chrome Console:

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

defineSlot在第一个脚本中定义.此问题仅在每刷新10页时发生一次,因此在大多数情况下都可以.

The defineSlot is defined in the first script. This issue only occurs on around every 10 page refresh so most of the time its ok.

我想提供有关如何处理此问题的建议.以下是2个脚本:

I want advise on how to deal with this issue. Below are the 2 scripts:

标题脚本:

<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 is the second script - this is only part of it (its quite 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 a script running another another method/function is loaded?

我可以创建某种依赖性吗?

Can I create some sort of dependency?

如何确保顶部JS在底部JS之前加载?

How can I ensure the top JS is loaded before the bottom?

推荐答案

将脚本存储在单独的文件中.然后,类似以下的内容应该起作用:

Store your scripts in separate files. Then something like 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);
}

loadScript函数将加载位于"pathToScript"的脚本,并在完成脚本加载后调用提供的回调.您需要回调,因为加载外部资源是异步操作.这意味着完成外部资源的加载后,您基本上需要一个通知".基本上,这就是回调的作用.如果您依赖于来自异步操作的数据,则无法启动该操作,然后继续尝试使用该数据或资源,因为该数据尚未完成加载.因此,任何依赖于资源的代码都放在回调中.我们为什么要这样做,稍后会更清楚.

The loadScript function loads a script that resides at "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. Which means that you basically need a "notification" when it has finished loading the external resource. This is basically what a callback does. If you depend on data that comes from an asynchronous operation, you cannot fire off the operation and then go ahead and try to use the data or resource because the data will not have finished loading. So any code that depends on the resource, you put inside the callback. Why we're doing this will be clearer later on.

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);

scripts数组包含要加载的脚本数组.该顺序由脚本在数组中的位置暗示.因此,将在scripts[1]处的脚本之前加载位于scripts[0]处的脚本.

The scripts array contains an array of scripts to load. The order is implied by the position of the script in the array. So a script that is at scripts[0] will be loaded before a script at scripts[1].

load函数可确保按所需顺序加载脚本.我们知道加载操作是异步的.我们也知道一旦操作完成,就会调用一个回调函数.使用该信息,我们可以在第一个脚本完成加载后加载第二个脚本. load有一个参数,它表示scripts数组的当前索引.我们最初将索引i设置为0,这意味着我们将首先在索引0处加载脚本.然后,我们查看i的值.如果它小于数组的长度,则意味着我们还没有完成所有脚本的编写(请将其视为循环).因此,如果i小于长度,我们用scripts[i]的值调用loadScript函数.然后在回调中,再次调用load函数,但是这次我们增加i的当前值.因此,当脚本完成加载后,我们最终以递增的索引调用load,因此现在可以加载下一个脚本.

The load function is what ensures that you're loading your scripts in the desired order. We know that the loading operation is asynchronous. We also know that a callback will be called once the operation is done. Using that information, we can load the second script after the first script finishes loading. There is one argument to load, which represents the current index of the scripts array. We set the index i initially to 0, which means that we're going to load the script at index 0 first. We then look at the value of i. If it is lesser than the length of the array it means that we're not done going through all the scripts (think of it as a loop). So if i is lower than the length, we call the loadScript function with the value of scripts[i]. Then in our callback, we call our load function again but this time we increment the current value of i. So when the script has finished loading, we end up calling load with the incremented index and so we can now load our next script.

如果i等于scripts.length,则意味着我们已经加载了所有脚本,因此将进入else块,这是您放置所有需要运行的代码的地方脚本已加载.

If i is equal to scripts.length, it means that we have loaded all our scripts and so we will go into the else block, and this is where you put the code that you need to run after all scripts have been loaded.

最后一行是对load的实际调用,其参数为0,它从第一个脚本的路径(位于scripts数组的索引0处)开始,开始了整个过程.

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

如果愿意,您也可以将load函数重写为IIFE:

You can rewrite the load function as an IIFE as well, if you wish:

(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 the callback. It is functionally equivalent to the less-exotic version above.

这篇关于JavaScript加载顺序导致问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆