[FRAGE] Javascript/Jquery Klasse - Methode aus Methode heraus aufrufen. Oder anderes Problem?

Pichen

New member
Hi,

ich arbeite mit Jquery und Sharepoint und versuche un einer Klasse 2 Abfragen auf den Sharepoint zu machen, um mir meine Daten zusammenzusammeln, um dann auf diesen Daten Berechnungen durchzuführen.
Soweit die Theorie.
In meinem Verständnis für Klassen und und Objekte müsste der Code so funktionieren.

Ich habe aber mittlerweile das Gefühl, dass ich grundsätzlich etwas falsch mache.

Wenn ich meinen Code ausführe, kommt er bis this.F_GotIssueData und sagt mir dann dass this.F_GetVolumes() nicht definiert ist.

Da ich euch keinen Zugriff auf den Sharpoint geben kann, ist der gepostete Code nicht ausführbar und greift auf Dummyfunktionen zurück.
Aber vielleicht sieht ja ein Javascript und Ajax Profi auch unter diesen schlechten Bedingungen was hier schief läuft.

Code:
function F_SomeFunctionThatBuildsMeAQuery()
{
    //Dummy
}

function F_SomeFunctionThatBuildsMeAnotherQuery()
{
    //Dummy
}


function C_Analysis(sDate, sLine, sShift)
{
    this.bIssueReady = false;
    this.bVolumeready = false;

    this.sDate = sDate;
    this.sLine = sLine;
    this.sShift = sShift;

    this.oIssueList;
    this.oVolumeList;    
    
    
    this.F_GetVolumes=function()
    {

        
        var l_QueryUrl = F_SomeFunctionThatBuildsMeAQuery();            
     

        $.ajax({
            url: l_QueryUrl,
            headers: {"accept": "application/json;odata=verbose"},
            method: 'GET',
            success: this.F_GotVolumeData,
            error: function (oData) {
                console.log("VOLUME FEHLER");
                console.log(oData);
            }
        });

    };

    this.F_GotIssueData = function(oData)
    {
        if (oData)
        {

            this.oIssueList = oData.d.results;
            console.log("ISSUE");
            console.log(this.oIssueList);
            this.F_GetVolumes();
        }
    };
    
   
    
    this.F_GetIssueData = function ()
    {

        var oStartEndTime = F_GetStartEndTime(this.sDate, this.sShift);

        var sFilter = F_SomeFunctionThatBuildsMeAnotherQuery();
        
        $.ajax({
            url: l_QueryUrl,
            headers: {"accept": "application/json;odata=verbose"},
            method: 'GET',
            success: this.F_GotIssueData,
            error: function (oData) {
                console.log("ISSUE FEHLER");
                console.log(oData.d.results);
            }
        });

    };


    this.F_GotVolumeData = function (oData)
    {
        if (oData)
        {
            this.oVolumeList = oData.d.results;
            this.bVolumeReady = true;
            console.log("VOLUME");
            console.log(oData.d.results);

        }
    };
    
     this.F_GetIssueData();
 }

Erst habe ich gedacht dass es daran liegt, dass ich eine Methode aus einer Methode heraus aufrufe. Deswegen habe ich folgendes Testskript geschrieben. Das funktioniert aber ohne Probleme. Und nun bin ich vollkommen verwirrt.

Code:
<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        
        <script src='jquery-1.11.3.js'></script>
    </head>
  
    <body>
        <style type="text/css"> 
            .rahmen
            {
                border: 1px solid black;                
            }
            .hintergrund
            {
                border: 1px solid black;
                background-color: #ADFFC5;
            }
        </style>
        <script>
           function C_TestKlasse()
           {
               this.sAttribut1 = 'Hallo';
               this.sAttribut2 = 'Welt';
               
               this.F_Methode1 = function()
               {
                   $('#haupt').append($('<div>', {class: "rahmen", id:'div1'}));
                   $('#div1').append(this.sAttribut1);
                   this.F_Methode2();
               };
               
               this.F_Methode2 = function()
               {
                   $('#haupt').append($('<div>', {class: 'hintergrund', id: 'div2'}));
                   $('#div2').append(this.sAttribut2);
               };
               this.F_Methode1();
           }
           
           $(document).ready(
            function () {
                var oMyObject = new C_TestKlasse(); 


            }

);
        </script> 
        <div id='haupt'>
        
         </div>
    </body>
    
</html>
 
Aber vielleicht sieht ja ein Javascript und Ajax Profi auch unter diesen schlechten Bedingungen was hier schief läuft.
in einem Wort: Scope.

jQuery verwendet in seinen AJAX-Handlern einen anderen Scope, weswegen this nicht mehr das von dir beabsichtigte Objekt ist.

Abhilfe schafft da ein Closure:
Code:
success: this.F_GotVolumeData.bind(this),
 
danke, danke, danke danke danke! Das hat mir sehr viele graue Haare erspart. :)

Jetzt tut sich allerdings gleich die nächste Frage auf: Diese Ajax Aufrufe brauchen eine gewisse Zeit bis die Daten vorhanden sind.
Im Moment schachtel ich meine Anweisungen und rufe die nächste Get Funktion in der success Funktion des aktuellen Aufrufs.
Das ist nicht wirklich schön lesbar.

Schön wäre so etwas:

Code:
if (this.F_GetFirstData().Success = true)
{
     if(this.F_GetSecondData().Success=true)
     {
         this.F_GetThirdData();
     }
}

Ein zweites Problem ist: Ich bräuchte eine Möglichkeit, dem Browser mitzuteilen dass meine Objekt der Klasse C_Analysis jetzt alle Daten hat und jetzt damit weitergearbeitet werden kann.
Kann ich eigenes Event feuern?
 
mit Promises geht das sogar noch viel schöner!

mal als Pseudo-Code
PHP:
// same setup for second/third/…
getFirstData = function () {
    // without the success handler!!!
    return $.ajax({…});
}

obj
    .getFirstData()
    .done(function (data) {
        // do something with data…
        return obj.getSecondData();
    })
    . done(function (data) {
        // do something with data…
        return obj.getThirdData();
    })
    . done(…)

- - - Aktualisiert - - -

Ein zweites Problem ist: Ich bräuchte eine Möglichkeit, dem Browser mitzuteilen dass meine Objekt der Klasse C_Analysis jetzt alle Daten hat und jetzt damit weitergearbeitet werden kann.
Kann ich eigenes Event feuern?
du kannst dafür einen Event feuern, oder auch wieder Promises verwenden.

Promises kurz zusammengefaßt: Das Arbeiten mit Werten, die es noch nicht gibt.

- - - Aktualisiert - - -

und nochwas, Objektmethoden gehören in den Prototype (wenn’s keine Closures sind).
 
Sorry ihr habt mich jetzt ein bisschen abgehängt :/

Aber bevor ich euch mit Fragen löchere ...

Ist es überhaupt sinnvoll sich so die Daten innerhalb von einer Klasse zu holen?
Ich habe im Moment das Problem, dass ich mir mit jedem Problem das ich löse, eine neue große Baustelle aufmache.
 
Sorry ihr habt mich jetzt ein bisschen abgehängt :/
Das tut mir leid. Frag' einfach konkret, was du nicht verstehst.

Ist es überhaupt sinnvoll sich so die Daten innerhalb von einer Klasse zu holen?
Das kommt darauf an. Wenn die Daten, die du holst voneinander abhängen, musst die Daten natürlich so hintereinander holen. Wenn sie unabhängig sind, ist es sinnvoller, die Requests gleichzeitig zu starten und dann zu warten, bis alle Daten da sind (Promises sind dafür eine gute Lösung).
Wenn die Daten zu den Instanzen gehören, ist es auf jeden Fall sinnvoll, diese auch erst in der "Klasse" zu holen. Wenn nicht, würde ich die Daten statisch an den Konstruktor packen.
Ich habe im Moment das Problem, dass ich mir mit jedem Problem das ich löse, eine neue große Baustelle aufmache.
Das ist relativ normal, wenn man eine neue Sprache lernt.
 
Ok ...

Ich versuche mal nach und nach die Knoten in meinemHirn zu entwirren.

Da gibt es Klassen in Javascript, die aber mit dem Schlüsselwort 'function' erstellt werden.
Es gibt Objekte von Klassen, aber auch instant Objekte, die mit 'var' definiert werden können.
Es gibt eine Art Zugriffsmodifikatoren. Aber nicht die gewohnten Private, Protected und Public, sondern Private, Public und Priviliged.

Wenn ich es richtig verstehe, legt man public Functions im Prototype an. Also ausserhallb der Klassendefinition. Public Variablen werden aber mit 'this' gekennzeichnet und befinden sich innerhalb der Klassendefinition. Methoden, die mit this gekennzeichnet sind und in der Klassendefinition angelegt sind, werden mit Erstellung des Objekts ebenfalls erstellt und heissen dann Priviliged. Der Prototype scheint eine Art Ressource zu sein, aus der sich ein Objekt bedient ohne eine 'Instanz' der Methode zu erstellen.

- habe ich das richtig verstanden?
Wenn ja: Macht es so einen großen Unterschied, ob die Methode instaziiert wird oder nicht?
Kann ich auch Variablen im Prototype definieren?
Ist der Prototype so eine Art abstrakte Klasse von der meine Klasse erbt?

Private Variablen und Funktionen befinden sich innerhalb der Klassendefinition und sind dadurch zu erkennen, dass kein this vorangestellt ist. Sie sind (hoffentlich) nach aussen nicht sichtbar.

Und privieiged Functions machen mich fertig. Die kann ich überhaupt nicht einordnen. Die sind wie public, können aber auf private Variablen zugreifen? Heisst das, public Functions, die per Prototype definiert werden, können das nicht? Wenn ja kann man public Functions doch nur verwenden, wenn man nicht auf private Variablen zugreifen will.
Dann wären public Functions in meinen Augen recht sinnlos. Jedenfalls wenn man versucht, seine Daten zu kapseln und möglichst wenige Klassenvariablen public zu machen.

Funktioniert das Konzept von public und private überhaupt so, wie man es aus php, c++ etc. kennt?

Fragen über Fragen :)
 
Zuletzt bearbeitet:
Zurück
Oben