Mam jeden plik JS w nagłówku (to jest dla Google DFP) i inny przed </body>

Znalazłem, jeśli plik Header JS nie ładuje się przed dolną, otrzymam ten błąd w konsoli Chrome:

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

Defineslot jest zdefiniowany w pierwszym skrypcie. Ten problem występuje tylko wokół każdej 10 odświeżania strony, więc przez większość czasu jest OK.

Chcę doradzić, jak radzić sobie z tym problemem. Poniżej znajdują się 2 skrypty:

Skrypt nagłówka:

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

Poniżej znajduje się drugi skrypt - to tylko część (jest dość długi):

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

Czy jest jakiś sposób na zatrzymanie skryptu, który jest załadowany inną metodą / funkcją?

Czy mogę stworzyć pewną zależność?

Jak mogę zapewnić, że najlepszy JS jest załadowany przed dnem?

4
Adam 6 wrzesień 2012, 02:53

3 odpowiedzi

Najlepsza odpowiedź

Przechowuj swoje skrypty w osobnych plikach. Wtedy coś takiego powinno działać:

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

Funkcja loadScript ładuje skrypt, który znajduje się w "Pathtoscript", a po zakończeniu ładowania skryptu, wywołuje dostarczone wywołanie zwrotne. Potrzebny jest zwrotny, ponieważ ładowanie zasobu zewnętrznego jest operacja asynchroniczna. Co oznacza, że w zasadzie potrzebujesz "powiadomienia", gdy zakończył ładowanie zasobu zewnętrznego. Jest to w zasadzie co do wywołania zwrotnego. Jeśli polegasz na danych, które pochodzi z operacji asynchronicznej, nie możesz strzelać z operacji, a następnie przejść do przodu i spróbuj użyć danych lub zasobów, ponieważ dane nie zostały zakończone ładowanie. Więc każdy kod, który zależy od zasobu, umieścisz w wywołaniu zwrotnym. Dlaczego to robimy, będzie jasne później.

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

Array scripts zawiera tablicę skryptów do ładowania. Zamówienie jest dorozumiane przez położenie skryptu w tablicy. Skrypt, który jest w scripts[0] zostanie załadowany przed skryptem w scripts[1].

Funkcja load jest tym, co zapewnia, że ​​ładujesz skrypty w żądanej kolejności. Wiemy, że operacja ładowania jest asynchroniczna. Wiemy również, że wywołanie zwrotne zostanie wywołane po zakończeniu operacji. Korzystając z tych informacji, możemy załadować drugi skrypt po zakończeniu załadunku pierwszego skryptu. Jest jeden argument do load, który reprezentuje bieżący indeks tablicy scripts. Ustawiamy indeks i początkowo do 0, co oznacza, że ​​najpierw załadujemy skrypt w indeksie {x5}}. Następnie patrzymy na wartość i. Jeśli jest mniejszy niż długość tablicy, oznacza to, że nie przeprowadzamy przechodzenia przez wszystkie skrypty (pomyśl o tym jako pętlę). Więc jeśli i jest niższa niż długość, nazywamy funkcję loadScript za pomocą wartości scripts[i]. Następnie w naszym wywołaniu zwrotnym nazywamy ponownie naszą funkcję {{x10}}, ale tym razem zwiększamy bieżącą wartość i. Więc kiedy skrypt zakończył ładowanie, wywołamy load za pomocą indeksu zwiększonego, a więc możemy teraz załadować nasz następny skrypt.

Jeśli i jest równy scripts.length, oznacza to, że załadowaliśmy wszystkie nasze skrypty, a więc pójdziemy do bloku else, a to właśnie włożyłeś kod, którego potrzebujesz biegnij po załadowaniu wszystkich skryptów.

Ostatnia linia jest rzeczywistym połączeniem do load, z argumentem 0, która rozpoczyna cały proces, rozpoczynając od ścieżki do pierwszego skryptu, który znajduje się w indeksie 0 {X3}} Array.

Możesz przepisać funkcję load jako iife, jeśli chcesz:

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

Tutaj masz funkcję "samokrofędną", która nazywa się w wywołaniu zwrotnym. Funkcjonalnie równoważna powyżej wersji mniejszej egzotycznej powyżej.

4
Vivin Paliath 28 styczeń 2015, 15:42

Inne rozwiązania mogą działać, ale prawdziwą kwestią ma wspólnego z drogą, w jaki używasz DFP.

DFP jest ładowany asynchronicznie, aby metoda definesseł nie istnieje na stronie w momencie wykonywania skryptu, który powoduje błąd, jest wykonywany.

Cały kod DFP powinien być zawarty w opakowaniu googletag.cmd.push, który przechowuje polecenia do momentu załadowania DFP, a następnie wykonać je w odpowiedniej kolejności.

Wystarczy owijać jakikolwiek kod DFP, taki jak więc, powinien naprawić błędy:

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

});
6
Community 26 listopad 2015, 13:04

Możesz utworzyć własne wydarzenie, powiedzmy, powiedzmy first_script_loaded, a gdy pierwszy skrypt zostanie załadowany, możesz dodać na końcu $(document).trigger("first_script_loaded"), możesz również skonfigurować globalny boolean tylko w tym miejscu, gdzie Jest ustawiony na false na początku, a po załadowaniu 1st skrypt, ustawisz go do true

W drugim skrypcie sprawdź, czy boolean jest true, co oznacza, że pierwszy skrypt został już załadowany przed uruchomieniem drugiego skryptu, ale jeśli jest fałszywy, a następnie słuchaj zdarzenia {{ X2}} i dodaj kod w callback metody on.

0
zeacuss 5 wrzesień 2012, 23:08