Indexed DB - DB Variable is undefined

  • Hey,


    in meinem Code habe ich außerhalb einer Funktion eine Variable deklariert. Beim Ausführen einer Funktion mit der IndexedDBVerbindung prüfe ich ob die Verbindung auch erfolgreich aufgebaut wurde. Dort weis ich dieser Variable die außerhalb liegt das Ergebnis vom Event zu:


    JavaScript
    1. let db;
    2. let request = window.indexedDB.open("Meetings", 2);
    3. request.onsuccess = function(event){
    4. db = event.value.result; // <--- Hier
    5. console.log(db);
    6. console.log("Datenbankverbindung wurde erfolgreich hergestellt");
    7. };

    Wenn ich nun db im onsuccess in der Konsole ausgebe ist diese mit den richtigen Daten befüllt.

    Nun wenn ich jedoch die db-Variable außerhalb in der Konsole ausgebe ist diese undefined.


    Warum ist das so? Wird der Wert der innerhalb der Funktion gesetzt wird nicht der let db; zugewiesen die außerhalb definiert wurde?


    Grüße

  • Hi Stef,


    ich würde dir hier empfehlen dir mal anzuschauen wie var, let und const in JS am sinnvollsten zu verwenden sind. var und let haben etwas mit dem Scope zu tun und let ist beschränkt auf den scope.


    https://developer.mozilla.org/…/Reference/Statements/let

    https://developer.mozilla.org/…/Reference/Statements/var


    Generell würde ich dir empfehlen bei Skripten die bestimmte aufgaben erfüllen Klassen zu nutzen, da du den Scope hier viel einfacher handeln kannst. Wenn du ES6 nutzen kannst, dann kannst du die JS Klassen normal verwenden:


    https://developer.mozilla.org/…aScript/Reference/Classes


    Wenn du an ES5 gebunden bist, dann geht das auch, wird aber etwas anders geschrieben:


    https://dev.to/_hridaysharma/u…ritance-in-javascript-n8d


    (Oder du wechselst auf TypeScript und lässt das die generierung Händeln ;) https://www.typescriptlang.org/)


    Grüße


    Timo

  • Hier noch ein Nachtrag, weil ich nicht alle infos gegeben habe. Das es hier mit let nicht funktioniert hängt daran "wo" die Funktion aufgerufen wird.


    Anders würde es funktionieren. Bsp:

    Code
    1. let db
    2. var test = {callback: function() { db = "testvalue"; console.log(db);}}
    3. test.callback()
    4. console.log(db)

    Hier funktioniert das auch mit let, weil der scope nach unten durchgegeben wird (aber nicht nach außen, wenn man let auch in der Funktion benutzt).


    Bei deinem Code ist es zwar dennoch ein "let" Problem, liegt aber daran, das der Aufruf der Funktion an einer ganz anderen stelle passiert, in der der scope von let db; nicht mehr vorhanden ist.


    Bei var sollte es funktionieren, weil var die variable in den globaln Scope (sprich, an das window objekt) hängt.


    Nur noch als Nachtrag.


    Grüße


    Timo

  • Hi,


    danke für deine Antwort :)


    bisher hat es mit let bei mir immer problemlos funktioniert. Die let Variable die im Außen definiert ist kann ihren Wert innerhalb einer Funktion auch zugeweist bekommen - siehe auch https://jsfiddle.net/zvL6xhke/ -


    Der Scope von der let Variable ist nicht auf die Funktion beschränkt sondern global in dieser Datei weil diese am Anfang außerhalb einer Funktion deklariert wurde.

    Wenn ich diese innerhalb deklariere hat dies keine Auswirkung auf die außerhalb deklarierte weil es ein anderer Scope ist.


    Bei Var wird die Value bei neu setzten der gleiche Variable überschrieben. Wenn ich die Value jedoch nur zuweise wird diese auch in dieser abgespeichert. So wie bei let.


    Ich habe es nochmal getestet:

    In der index.html wird alles problemlos ausgeführt. Wenn ich die database.js in der die ganze IndexedDB Funktionalität steht in die meeting.html einbinde und dort eine Funktion ausführe kommt immer: db ist undefinded. Warum das so ist weiß ich nicht.


    Dein Ratschlag die Datenbankaktionen in eine Klasse zu packen finde ich sehr gut - und werde ich auch machen. :)


    In TypeScript werde ich mich wenn ich mehr Zeit zu Verfügung habe einarbeiten. In den wenigen Tagen die mir noch zur Verfügung stehen ist dies jedoch nicht machbar.


    Schöne Grüße,

    Stef



  • Gut, jetzt kommen wir in die Scope-hölle von JS, das Problem kann hier dennoch bleiben, das etwas anderes den Scope schließt, bzw. das der Aufruf der "onsuccess" irgendwo anders passiert.


    Das ordentlich zu Debuggen ist nervig (Deswegen war die Idee durch einen eigenen definierten Scope wie eine Klasse das zu kapseln). Sagen wir du hast irgendwo ausersehen eine andere var db oder let db stehen und übersehen, dann könnte es sein, das dieses dein Scope überschreibt.

    Oder du rufst die Funktion in einer anderen Funktion auf, welche dann wieder einen eigenen scope hat.


    Aber um das raus zu finden müsste man den gesamten Code sehen :).


    Grüße


    Timo

  • Ich habe jetzt einiges ausprobiert und habe herausgefunden, dass wenn ich diese Funktion einem Button als onclick mitgebe, diese ausgeführt wird.


    Warum erst bei einem Click?

    Ich glaube ich habe es raus. Ich habe gelesen, dass DB Indexed asynchron läuft. Heißt nicht von oben nach unten sondern zeitversetzt (so wie ich es gelernt habe). Weil die Datenbank jedoch aufgrund des asynchronen Aufrufs zum Zeitpunkt der Funktionsausführung welche synchron verläuft noch nicht vorhanden ist existiert auch noch keine Variable db und somit entsteht die Fehlermeldung.


    Mit der Funktion window.setTimeout werden die Daten ausgegeben, erfolgreich gelesen. Auch wenn ich nur als Zeitwert eine 1 eintrage. Weil dies ein asynchroner Aufruf ist. Aber warum muss dort diese Funktion angewendet werden wenn mit nur 1 Millisekunde die Daten erfasst werden können. Ist eigentlich das gleiche wie synchron nur um 1 Millisekunde später was eigentlich kein großer Unterschied ist.


    Nun bin ich dabei auf einer 2 Seite (meeting.html) die Daten anhand der mitgegebenen ID über die URL auszulesen. Dort wird jedoch kein Datensatz gefunden - als gäbe es auf dieser neuen Seite noch keine Daten in diesem Object Store.


    Ich habe da schon viel gegooglet - jedoch nichts dazu gefunden warum dies der Fall ist.


    Wie kann das sein?

  • Hm, ich sehe gerade das ich mit dem oberen teil doch unrecht hatte.

    Wenn es um das time out geht, hier wird ein eigener Prozess gestartet, welcher auch bei 0 Millisekunden immer noch länger braucht zum initialisieren als der aktuell laufende Programmcode. Normalerweise sollte man hier dann anfangen mit Promisses oder callbacks zu arbeiten.


    Du kannst bei der IndexedDb aber auch mit await arbeiten, damit wartet dein Programm dann bis zum Ablauf. Wichtig ist, sobald du anfängst mit Asynchronen Prozessen zu arbeiten, musst du IMMER auf anderen Wege sicherstellen das die resourcen da sind auf die du wartest. In vielen Sprachen hast du dazu await, oder generell Promises auf die du warten kannst.


    Der alte weg in JS war, bevor Promises und await kam, eine eigene timeout Funktion zu schreiben die wartet bis alle notwendigen Ressourcen da sind.


    https://medium.com/@filipvitas…-async-await-3d047dddd313



    Grüße


    Timo