Jak tworzyć przestrzenie nazw z funkcjami? "Uncaught ReferenceError: <namespace> is not defined"

0

Cześć.
Próbuję stworzyć namespace w osobnym pliku js. Namespace zwie się "UTILS.tokens" i zawiera metody pomocnicze, które dodają token CSRF do nagłówka w każdym zapytaniu ajaxowym typu post, put, delete. Pobierają również token z responsa i wsadzają do metatagów na stronie jeśli potrzeba (przed autentykacją oraz rejestracja, które są na na oddzielnych stronach). Chce wysyłać tokeny w nagłówkach i przechowywać w metatagach więc double cookies mnie nie interesują.
Problem jest taki, że dostaje błąd w javascript jak i jQuery:

"Uncaught ReferenceError: UTILS is not defined"

Ogólnie wcześniej działało, ale kod się powtarzał więc chciałem to oczyścić i zrobić jeden reużywalny, niestety sie sypło i nie wiem co jest źle, bo to mój pierwszy raz . Czy sposób w jaki event listenera używam w namespace jest dobry i czy dobrze sie odwołuje...
Przykładowy kod:
namespace w utils.js:

UTILS = UTILS || {};
UTILS.tokens = UTILS.tokens || {};

UTILS.tokens.getCsrfToken = (function (jqXHR) {
    $('meta[name="X-CSRF-TOKEN"]').attr('content', jqXHR.getResponseHeader('X-CSRF-TOKEN'));
    $('meta[name="X-CSRF-HEADER"]').attr('content', jqXHR.getResponseHeader('X-CSRF-HEADER'));
});

UTILS.tokens.setHeaderWithCsrfToken = (function (jqXHR) {
    var token = $('meta[name="X-CSRF-TOKEN"]').attr('content');
    var header = $('meta[name="X-CSRF-HEADER"]').attr('content');
    jqXHR.setRequestHeader(header, token);
});

UTILS.tokens.setCsrfToken = (function () {
    return $.ajax({
        url: '/token',
        type: 'GET',
        timeout: 3000
    }).then(function (data, textStatus, jqXHR) {
        getCsrfToken(jqXHR);
    }, function (jqXHR) {
        console.log('Problem with token retrieval occurred: ' + jqXHR.status);
    });
});

UTILS.tokens.attachToken = (function () {
    $(document).on('ajaxSend', function (element, jqXHR, settings) {
        if (settings.type === 'POST' || settings.type === 'PUT' || settings.type === 'DELETE') {
            setHeaderWithCsrfToken(jqXHR);
        }
    });
});

strona z logowaniem login.js:

$(document).ready(function () {

    UTILS.tokens.attachToken();
    UTILS.tokens.setCsrfToken(); // token has to be properly set, before post submit
    $('#loginForm').submit(function (event) {
        event.preventDefault(); 
        var data = 'username=' + $('#username').val() + '&password=' + $('#password').val();
        return $.ajax({
            url: '/login', // spring exposes login service on default at "/login" endpoint
            type: 'POST',
            data: data,
            timeout: 3000
        }).then(function () {
            var preLoginInfo = JSON.parse($.cookie("restsecurity.pre.login.request"));
            window.location.replace(preLoginInfo.url);
        }, function () {
            alert('Wrong Credentials, try again.');
        });
    });

    $('#registerBtn').on('click', function () {
        window.location = '/register.html';
    });
});
0

A jak to wg Cibie ma działać:

UTILS = UTILS || {};

?

0

@Maciej Cąderek: jeśli UTILS istnieje to zwróci ją sobie, a jeśli nie to utworzy pusty obiekt. Wziąłem to z książki "Wzorce projektowe"- stefan stoyanov z o'reilly. Próbowałem ze zwykłym ifem i typeof ale to samo. Jest chociażby tutaj w odpowiedziać też: https://stackoverflow.com/questions/5271663/sharing-a-js-functions-between-code-in-2-files

2

"Uncaught ReferenceError: UTILS is not defined"

Przecież masz pokazany błąd. Próbuje się odwołać do zmiennej UTILS, który nie jest zdefiniowana. Musiałbyś dać np. var:

var UTILS = UTILS || {};

ew. skorzystać z obiektu globalnego window

window.UTILS = window.UTILS || {} 

Inna sprawa, że tego typu pisanie, czyli tworzenie zmiennych globalnych, które traktujemy jako namespace'y raczej rzadko się już stosuje, bo zwykle pisze się aplikacje na modułach (moduły z ES6 albo CommonJS z NodeJS) a zmiennych globalnych (tutaj zmienna UTILS ma być zmienną globalną w końcu) raczej się unika (chyba, że do jakichś haków).

Co prawda użycie modułów nijak ci nie likwiduje zasad języka dotyczących niezdefiniowanych zmiennych (zmienna w module czy zmienna lokalna w funkcji też się wywali jak jej niezadeklarujesz jakoś), ale po prostu sprawia, że pewne praktyki, które kiedyś historycznie były stosowane, teraz straciły na znaczeniu. Kiedyś się wklejało ileś tagów script do pliku HTML i każdy skrypt dodawałby swój kawałek do UTILS - teraz się to rozwiązuje zwykle w w ten sposób, że jeden moduł importuje inne moduły, z których korzysta i eksportuje wszystko naraz (ew. moduł mógłby wystawiać jakieś API do robienia pluginów, jeśli chcielibyśmy mieć większą elastyczność).

0

@LukeJL: omg dzięki, chyba z tego wku**u takiej pierdoły nie widziałem. Ogólnie zastanawiam się czy nie zmienić podejścia i czy w jakiś sposób da się globalnie zdeklarować event handler, który będzie doklejał token do nagłówka przed każdym wysłaniem i drugi, który będzie sprawdzał czy przypadkiem nowy token z serwera nie przyleciał i doklejał go do metatagu na stronie, bądź lokalnie cookiesa. I nie musieć ich wywoływać na piechotę na kazdym pliku jsowym, tylko plik ze skryptem ładować na stronkach?

2

Jeszcze bym dodał, że lepsze window.UTILS niż var UTILS, bo to drugie opiera się na dwóch sztuczkach, pierwsza - hoisting, druga - redeklaracja zmiennej. Jakbyś chciał to przerefaktoroweć do aktualnej wesji js (let) to to nie zadziała.

0

Ogólnie zastanawiam się czy nie zmienić podejścia i czy w jakiś sposób da się globalnie zdeklarować event handler, który będzie doklejał token do nagłówka przed
każdym wysłaniem i drugi, który będzie sprawdzał czy przypadkiem nowy token z serwera nie przyleciał i doklejał go do metatagu na stronie, bądź lokalnie cookiesa

nie musisz tego robić. Wystarczy, że zamiast wywoływać ręcznie funkcję $.ajax, stworzysz jakąś dodatkową funkcję, coś w stylu:

function sendData(jakiesTamParametry) {
   // jakas tam magia z tokenami (nie wnikam juz co tam robisz)
   $.ajax(..........)
}

wtedy zamiast wywoływać ręcznie ajax i robić jakieś machinacje, będziesz wywoływać funkcję, która zrobi to z automatu.

0

Gdzie miałbym ją utworzyć i wywołać? To co przez ten pomysł chcę osiągnąć to uniknięcie właśnie wielokrotnego wywoływania funkcji. Tylko podać jakieś ustawienia ajaxa albo coś co będzie ogarniało wszystkie requesty ajaxowe. Bo mam po kilka w różnych plikach i póki co wywołuje w każdym pliku, a to takie brzydkie :<

1 użytkowników online, w tym zalogowanych: 0, gości: 1