Beiträge von AndreasB

    Hallo Christoph,


    Außerdem ist es für das Verständnis von async await wichtig zu wissen, dass sie auf Promise basieren.

    Eigentlich hatte ich vor die "_users" bei der Initialisierung zu laden

    Das kannst du immer noch so machen.

    Du kannst halt dein Programm erst starten, wenn alle Daten da sind. So wie du das Beispielsweise im Web machst, wenn du darauf wartest, dass der DOM vollständig geladen ist.


    In etwa so:

    JavaScript
    function main (users) {
        // Hier sind die User geladen
    }
    
    function err (reason) {
       // Hier landen wir wenn beim Laden ein Fehler auftrat.
    }
    
    loadUser().then(main, err);

    Es kommt natürlich immer darauf an, was du machen willst.


    Grüße

    Andreas

    Hallo Sempervivum,


    du hast recht, das scheint auf den ersten Blick widersprüchlich zu sein, ist es aber nicht.

    Der Begriff, "synchron" ist sehr dehnbar ;)


    Der Grund, weshalb es empfohlen wird, bei XMLHttpRequest.open() den asynchronous Flag zu setzen ist der, dass ohne diesen auch die Ausführung aller anderen Tasks den Browsers pausiert wird.


    Synchronous XHR requests often cause hangs on the web.


    Dies ist bei der Verwendung des await Keywords nicht so:

    Zitat von mdn


    "It does allow other tasks to continue to run in the meantime, but your own code is blocked."

    Wie der Browser das bewerkstelligt, kann ich dir aber leider nicht sagen.



    Grüße

    Andreas

    Hallo Christoph,


    Zitat

    Wie bekomme ich die User in den Kontext der aufrufenden Klasse?

    Kurze Antwort: Niemals!


    Erklärung:

    was du hier erlebst, ist die größte Herausforderung bei der Asynchronen Programmierung: Die Asynchronität.


    Wenn man sich die Reihenfolge anschaut, in der die Funktionen aufgerufen werden, sieht man auch warum:


    Zusammengefasst, existieren die Daten nur im Scope (Kontexts) des onLoadUsers Callbacks.

    Wenn du also mit den Daten weiterarbeiten möchtest, musst du das in diesem Scope tun.


    Ich hoffe ich konnte ein wenig Klarheit in dieses Thema bringen, es ist mit das schwerste, was in der Programmierung existiert.



    Grüße

    Andreas

    Hi Christoph1972


    Schau' dir mal das an:

    Making asynchronous programming easier with async and await (mdn)

    Callbacks, Promises, and Async (scotch.io)


    Die Methode (LoadUsers) die dein Modul zur Verfügung stellt, ist mit async gekennzeichnet.

    Das bedeutet, das der Rückgabewert auf jeden Fall ein Promise ist.

    Zitat

    console.log(users);// Hier ist Users immer leer.

    Die Variable users ist hier warscheinlich nicht wirklich "leer" sondern enthält ein Promise, das du ganz einfach auflösen kannst.

    Entweder mit einem .then()oder mit einem vorangestellten await (in einem async Kontext)


    Das Beispiel, dass du zum Schluss gepostet hast, ist eine Variante, die mit "callbacks" arbeitet. (Siehe die Links)

    Das hilft dir hier aber auch nicht weiter, denn dein Modul benutzt die Promise API und keine "callbacks"


    Grüße

    Andreas

    Das Prinzip das hier zu Grunde liegt ist der Unterschied zwischen Inline- und Block-Elementen (block-inline-elemente-in-html)


    <span> ist ein Inline-Element.


    Der Grund weshalb der Validator hier meckert ist der, dass in Inline-Elementen nur Inline-Elemente zulässig sind.

    Grob ist die Regel so: In Block-Elementen sind sowohl Inline- als auch Block-Elemente zulässig. In Inline-Elementen sind nur andere Inline-Elemente zulässig.

    (Purer Text zählt hier zu Inline-Elementen)


    Das ist auch der Grund, weshalb der Hintergrund nicht zu sehen ist.

    Wenn man den <p> Elementen ein `display:inline` verpasst, oder sie in <span> Elemente ändert, klappt das auch mit dem Hintergrund.
    Dann muss man allerdings die Zeilenumbrüche selber setzen (zB mit <br/>)


    Grüße

    Andreas

    Wenn du im False-Block von Ternary Operator zusätzlich eine Funktion aufrufen möchtest kannst du das mit dem Comma Operator tun.

    Dieser fügt beliebig viele Ausdrücke zusammen und gibt den letzen davon zurück.


    Das würde dann zB so aussehen.

    Code
    var classToApply = ausgewaehlteAntwort == aktuelleFrage.antwort ? 'correct') : (dasRichtigeErgebnisAusgeben(), 'incorrect') ;


    Ich rate aber ausdrücklich davon ab, in einem Ternary Operator noch eine Funktion aufzurufen, denn das führt zu extrem schwer lesbaren Code.
    Besser wäre es den Ternary Operator an dieser Stelle aufzulösen und in einen normalen if-Block zu ändern.

    So in etwa:


    Code
    var classToApply = 'correct';
    
    if (ausgewaehlteAntwort !== aktuelleFrage.antwort) {
        classToApply = 'incorrect'
        dasRichtigeErgebnisAusgeben();
    }


    Ich hoffe das hilft dir.


    PS:

    Um dir besser helfen zu können, wäre der Codeausschnitt hilfreich.

    Du suchst ab dem übergeordneten <tr> nach dem Pfad table td .dunkel, demnach müsste es unterhalb von <tr> eine <table> geben, gibt es aber nicht. Deshalb wundere ich mich, dass das funktioniert.

    Hier eine Erklärung dafür: mdn: Element.querySelectorAll()

    Das standard Verhalten von Element.querySelectorAll() ist es, dass, nur der letzte Teil des Selektors überprüft wird.


    source.closest('tr').querySelectorAll('table td .dunkel'); ist als das gleiche wie: source.closest('tr').querySelectorAll('.dunkel');


    Wenn man den Kompletten Selektor berücksichtigt haben möchte gibt es die Pseudoklasse :scope.
    source.closest('tr').querySelectorAll(':scope table td .dunkel');
    würde kein Element selektieren.