NodeJS class wywolanie metody z klasy

0

Hej, pisze sobie klasy zgodnie z ES6 ponieważ nie chce wnikac w prototypy, skoro (z tego co wyczytalem) od ES7 beda "normalne" klasy w js z publicznymi/prywatnymi obiektami itd.

Napisalem sobie jakas tam klase, w ktorej wrzucilem sobie rozne metody. No i teraz z innego miejsca w kodzie (inny plik js) wywoluje 1 metode z tej klasy i owa metoda po odpaleniu ma wywolac kolejna metoda z tej samej klasy, zrobilem to mniej wiecej tak:

loadJson(adress)
    {
      blebleble{
        if(!err){
            let d= JSON.parse(body);
            data = d;
            this.jsonIsLoaded();
        }

    }

    async jsonIsLoaded()
    {
        //do something
    }

Metoda loadJson uruchamiana z inn ego pliku js wykonuje sie prawidlowo ale kiedy juz sie owy json zaladuje i ma sie wykonac metoda jsonIsLoaded wywala blad:
"Exception has occurred: TypeError
TypeError: this.jsonIsLoaded is not a function"

Szukalem i szukalem i znalazlem ze wlasnie w taki sposob sie wywoluje metody w klasie wiec skad ten blad?

1

Hej, pisze sobie klasy zgodnie z ES6 ponieważ nie chce wnikac w prototypy

Klas ES6 można używać, ale ponieważ nie chce wnikac w prototypy to błędne myślenie, ponieważ klasy z ES6 opierają się na prototypach właśnie. Od tego nie uciekniesz.

"Exception has occurred: TypeError TypeError: this.jsonIsLoaded is not a function"

pierwsze co robisz w takiej sytuacji to:

console.log(this.jsonIsLoaded);

albo:

console.log(this);

i patrzysz w konsolę błędów, co ci wypluje.
wtedy widzisz, że skoro "is not a function" to wiesz, czym jest, albo czym nie jest.

No i teraz z innego miejsca w kodzie (inny plik js) wywoluje 1 metode z tej klasy i owa metoda po odpaleniu

Jak ją wywołujesz dokładnie? Nie mam szklanej kuli, to wygląda tak na oko, na to, że próbujesz wyciągnąć funkcję z obiektu (ale pokaż kod, może robisz jeszcze inaczej).

ew. druga możliwość jaka mi przychodzi do głowy - wywołujesz to w jakimś callbacku i this się traci (JS nigdy nie był i nie będzie normalnym językiem, choćby z tego powodu, że this inaczej działa). Jeśliby tak było, to mógłbyś użyć "arrow function", ale znowu - nie mam szklanej kuli...

trzecia możliwość jaka mi przychodzi do głowy - próbujesz wywołać metodę instancji klasy jak metodę statyczną (i tutaj właśnie się przydaje znajomość prototypów, żeby odróżnić jedno od drugiego, i czemuFoo.bar to nie to samo co Foo.prototype.bar). Ale znowu - za mało kodu wrzuciłeś...

0

No wlasnie wiem ze klasy w es6 opieraja sie o prototypy ale podobno es7 bedzie bardziej "przyjazny".
Metode wolam standardowo:

 instance = new BaseTrader(some params);
  instance.loadJson();

do loadJson wchodzi, laduje jsona i sie wywala:> zaraz zerkne co wypluwa przy logowaniu.

1

Hej, aby uzyskać szybką pomoc to proponuję wkleić lepszy przykład albo wyjaśnić, czym jest ble ble ble {} bo wygląda to jakby był problem z zasięgiem this.

0

Luźna uwaga: nie powinieneś wołać metody asynchronicznej bez dalszego przetwarzania jej Promise lub wykonania await.

0

Wychodzi na to ze nie moge wywolac zadnej metody z klasy, moge je wywolywac tylko z zewnatrz:/
Szczegóły:

Podstawowy plik Main.js (to nie klasa), wyglada mniej wiecej tak:

var BaseTrader = require('./BaseTrader.js')     //W pliku Main.js zaciagam drugi plik js z klasa
var przyklad;

prepareTrader();
async function prepareTrader()
{
  info = await getInfo();
  orders = await getOrders();

  przyklad= new BaseTrader(callAPI, 0.027, 34, "GOLD", "PLN", orders, info);
  przyklad.loadOrderBook();
}

Teraz w debugerze wskakuje do klasy BaseTrader ktora wyglada tak:

class BaseTrader
{
    constructor(callAPI, DIF, TRANSACTION_SIZE, ITEM, currentItem, orders, info, toBuy = -1, toSell = -1 )
    {
        this.callAPI = callAPI;
        this.DIF= DIF;
        this.TRANSACTION_SIZE = TRANSACTION_SIZE;
        this.ITEM= ITEM;
        this.currentItem= currentItem;
        this.orders = orders;
        this.info = info;
        this.toBuy = toBuy;
        this.toSell = toSell;
    }

    //Return object with  available propositions.
    loadOrderBook(item= this.ITEM, currentItem= this.currentItem)
    {
    request("https://something.net/API/Public/" + item + currentItem + "/orderbook.json", function (err, res, body){
        if(!err){
            let b = JSON.parse(body);
            book = b;
           console.log(this.dupa()); // <<<----   OUTPUT: TypeError: this.dupa is not a function
           console.log(this.dupa);// <--- OUTPUT: undefined
            this.dupa();// OUTPUT: TypeError: this.dupa is not a function
            dupa();// <----- OUTPUT: ReferenceError: dupa is not defined
            //console.log(jsonIsLoaded);
           // this.jsonIsLoaded();
        }
        else
            console.log("Error with request json: " + err);
     });
    }

    dupa(){
        console.log("TU odpalila sie dupa!!")
    }

//owa klasa eksportuje sie tak:
module.exports = BaseTrader;

Wywala ze metoda dupa nie jest zdefiniowana: ReferenceError: dupa is not defined
W necie znalazlem tylko 1 strone z informacja, jak wywolywac metody danej klasy w danej klasie i teoretycznie powinno smigac.
Tyle ze to jest nodejs, tutaj nie da sie wywolac innej metody w tej samej klasie czy jak?
Zalezalo mi na klasach poniewaz chcialem sobie stworzyc podstawowa klase danego obiektu ktora moglbym rozszerzać o konkretne wlasciwosci dla konkretnego obiektu ale cos mi to idzie jak krew z nosa :/

0

function tworzy nowy kontekst (zmienia Twoje this) - musiałbyś wykorzystać funkcję strzałeczkową (arrow function).

0

sorki oczywiscie w klasie bylo dupa(){} a nie function dupa(){} function od razu sie podkresla, gdzies mi sie wkleil kod z ktorym kombinowalem;p Edytowalem post wyzej naturalnie, temat nadal aktualny.

1

function (err, res, body){ - to tworzy nowy kontekst.

2

Dokładnie tak jak myślałem i tak jak @Patryk27 mówi - zmienia się kontekst.

oprócz arrow function jak wspomniał kolega wyżej to w prosty sposób możesz stworzyć na początku funkcji loadOrderBook jakąś zmienną, która zachowa this np. const self = this i później już odwoływać się do innych metod za pomocą self - np. self.dupa(). To jest stary sposób na radzenie sobie z tym problemem, ale ogólnie widzę, że raczej się uczysz to na tę chwilę możesz się pobawić w taki sposób.

A poza tym z całym tym requestem chyba lepiej przejść w całości na async/await albo przynajmniej na Promise bo teraz na zewnątrz obiektu nie masz jak kontrolowac tego kiedy request się skończy. (No chyba, że tak ma być ;-))

0

Kuuurcze hehe to dlatego w klasach js nie mozna uzywac slowa function bo sie kontekst zmienia? No tak masz w 100% racje ucze sie a wlasciwie przechodze z 1 juz chyba umarlego jezyka na drugi tyle ze ten opiera sie na prototypach a te cale klasy na dobra sprawe to wydmuszki. W sumie myslalem zeby pisac w typescript on jest skladnia niemal identyczny z moim starym jezykiem nawet jest wymuszone okreslanie typow i interfejsy ale stwierdzilem ze dobrze by popisac troszke w orginalnym js/nodejs.

Co do requesta to jest jakas zewnetrzna biblioteka i wyszedlem z zalozenia ze owy request sie tym zajmuje. W moim starym jezyku normalne bylo to ze powiedzmy loaderem ladowalo sie jakies rzeczy (xml/json/txt/grafika) i podpinalo sie do niego sluchacza na zakonczenie ladowania. Tutaj do ansynchronicznych rzeczy sa albo te metody .then{blebleble} albo await (jak mi doskonale wyjasnil kolega Maciej Cąderek w innym watku).
Czyli rozumiem ze moje zalozenie dotyczace requesta jest niesluszne i owa metoda loadOrderBook tez powinna sie opierac na await albo na then? :)

Jak by nie bylo dzieki za odpowiedz panowie, glowilem sie nad tym kawal czasu a nie zauwazylem owej funkcji ktora zmienia kontekst:> Swoja droga gdzies kiedys ogladalem tutki nijakiego Kyle Simpsons (polecam kolesia) i nawet byla o tym mowa ale oczywiscie nie powiazalem/przeoczylem ten fakt :) Dzieki jeszcze raz.

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