4

ヘッダーに 1 つの JS ファイル (これは Google DFP 用) と、その前に別の JS ファイルがあります。</body>

Chrome コンソールで次のエラーが発生する前に、ヘッダー JS ファイルが読み込まれない場合を見つけました。

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

defineSlot は最初のスクリプトで定義されています。この問題は約 10 ページの更新ごとにのみ発生するため、ほとんどの場合は問題ありません。

この問題に対処する方法についてアドバイスが欲しいです。以下に 2 つのスクリプトを示します。

ヘッダー スクリプト:

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

以下は 2 番目のスクリプトです。これはほんの一部です (非常に長い)。

$(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');
)};

別のメソッド/関数がロードされているスクリプトを停止する方法はありますか?

ある種の依存関係を作成できますか?

一番上の JS が一番下の JS の前にロードされるようにするにはどうすればよいですか?

4

3 に答える 3

6

ここにある他の解決策は機能するかもしれませんが、実際の問題は DFP の使用方法にあります。

DFP は非同期で読み込まれるため、エラーの原因となっているスクリプトが実行された時点では、defineSlot メソッドはページに存在しません。

googletag.cmd.pushすべての DFP コードは、DFP が読み込まれるまでコマンドを保存し、正しい順序で実行するラッパー内に含める必要があります。

DFP コードを次のようにラップするだけで、エラーが修正されます。

googletag.cmd.push(function() {
    // Double Click AD Variables

});
于 2012-09-06T14:13:33.323 に答える
4

スクリプトを別のファイルに保存します。次に、次のようなものが機能するはずです。

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」にあるスクリプトをロードし、スクリプトのロードが完了すると、提供されたコールバックを呼び出します。外部リソースのロードは非同期操作であるため、コールバックが必要です。つまり、外部リソースのロードが完了したら、基本的に「通知」が必要です。これは基本的にコールバックが行うことです。非同期操作からのデータに依存している場合、データの読み込みが完了していないため、操作を開始してから先に進んでデータまたはリソースを使用しようとすることはできません。したがって、リソースに依存するコードは、コールバック内に配置します。なぜこれを行うのかは、後で明らかになります。

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[0]にあるスクリプトの前にロードされscripts[1]ます。

関数は、loadスクリプトを目的の順序でロードすることを保証するものです。ロード操作が非同期であることはわかっています。また、操作が完了するとコールバックが呼び出されることもわかっています。その情報を使用して、最初のスクリプトの読み込みが完了した後に 2 番目のスクリプトを読み込むことができます。には、配列loadの現在のインデックスを表す1 つの引数があります。最初にscriptsインデックスを に設定します。これは、最初にインデックスでスクリプトをロードすることを意味します。次に の値を見ていきます。配列の長さよりも短い場合は、すべてのスクリプトの実行が完了していないことを意味します (ループと考えてください)。したがって、が長さよりも小さい場合、次の値で関数を呼び出しますi00iiloadScriptscripts[i]. 次に、コールバックでload関数を再度呼び出しますが、今回は の現在の値をインクリメントしますi。そのため、スクリプトのロードが完了するloadと、インクリメントされたインデックスを使用して呼び出すことになり、次のスクリプトをロードできるようになります。

iが に等しい場合scripts.length、すべてのスクリプトをロードしたことを意味するため、elseブロックに入ります。これは、すべてのスクリプトがロードされた後に実行する必要があるコードを配置する場所です。

load最後の行は、引数 を使用したへの実際の呼び出しであり、配列の0インデックスにある最初のスクリプトへのパスから開始してプロセス全体を開始します。0scripts

load必要に応じて、関数を IIFE として書き直すこともできます。

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

ここには、コールバックで自分自身を呼び出す「自己呼び出し」関数があります。これは、上記のあまりエキゾチックでないバージョンと機能的に同等です。

于 2012-09-05T23:17:49.193 に答える
0

たとえば、独自のイベントを作成できます。first_script_loaded最初のスクリプトが読み込まれたときに、最後に追加できます。また、最初に設定された、最初のスクリプトが読み込まれたときに、このためだけに$(document).trigger("first_script_loaded")グローバルを設定することもできます。、あなたはそれをに設定しますbooleanfalsetrue

2番目のスクリプトで、がであるかどうかを確認します。これbooleantrue、2番目のスクリプトの読み込みを開始する前に1番目のスクリプトが既に読み込まれていることを意味しますが、falseの場合は、イベントをリッスンし、メソッドのに$(document).on("first_script_loaded")コードを追加します。callbackon

于 2012-09-05T23:08:47.743 に答える