RFZ: synchrone Datenbankabfrage (HTML5 WebDatabase)

Moin,
ich würde gerne mittels HTML5 Features einen synchronen Zugriff auf die Browserdatenbank erzielen.

Laut HTML WebDatabase [w3.org] ist ein synchroner Zugriff vorgesehen, wird aber z.B. von Google Chrome nicht unterstützt.
Was funktioniert, ist der asynchrone Zugriff, der die Programmierung (in meinen Augen) bei vielen Queries schnell komplett unübersichtlich macht.
Auch ist ein fester Programmablauf extrem schwer zu kontrollieren.

Ich würde die asynchrone Schnittstelle daher irgendwie gerne synchron bekommen, scheitere aber leider daran.

  
// var db existiert global...  
			  
function testQuery(){  
	res = querySync('SELECT name FROM tabelle WHERE id = 115;');  
	alert(res); // liefert null ohne alert() in querySync()  
}  
  
function querySync(q,p){  
	this.completed = false;  
	this.result = null;  
	db.transaction(  
		function (transaction) {  
			transaction.executeSql(q,p,  
				function(t,r){  
					this.result = r;  
					this.completed = true;  
				}  
			);  
		},  
		function(e){  
			alert('SQL-Error in Query "'+q+'"\r\nError Message: '+e.message);  
		}  
	);  
	for(i=0; i<100; i++) wait(10);	// Wartezeit hat leider keinen Einfluss  
	alert('finished');	// mit alert() klappt es, ohne alert() kommt null zurück  
	return this.result;  
}  
  
// Typische wait-Funktion, aus dem Internet gekrallt  
function wait(millis) {  
	var date = new Date();  
	var curDate = null;  
	do { curDate = new Date(); }  
	while(curDate-date < millis);  
}  

Eigentlich wollte ich in einer Schleife auf this.completed warten.
Das problem ist, dass this.completed in der Funktion querySync() nicht aktualisiert wird.

Im obigen Beispiel (alert() auskommentiert) erhalte ich immer null zurück, egal wie lange ich mittels wait() warte.
Ist dagegen das alert() nicht auskommentiert, erhalte ich das SQL Result zurück.

Das alert() hält also offensichtlich die Ausführung der Funktion querySync() an, nicht aber die Ausführung des Callbacks, welches dann die Variable this.result ersetzen kann.

Sieht jemand von Euch eine Möglichkeit das Problem zu lösen?

  1. Grüße,
    willkommen im club - AFAIK unterstützt kein browser die sync-abfrage, ich fand auch keine lösun gund musste mir einen rekursiven mist zusammenkratzen.
    hat aber ein grund - die ist saulangsam :(
    5 aus 10 einträge zu SELECT (mit 5 bedingungen) dauert über 2 secunden
    MFG
    bleicher

    --
    __________________________-

    FirefoxMyth
  2. Hi,

    Was funktioniert, ist der asynchrone Zugriff, der die Programmierung (in meinen Augen) bei vielen Queries schnell komplett unübersichtlich macht.
    Auch ist ein fester Programmablauf extrem schwer zu kontrollieren.

    Ach was. Asynchronität ist heute Entwickler's täglich Brot, auch bei AJAX und generell auch beim Arbeiten mit Eventhandling.

    Sorge dafür, dass deine Anwendung mit der ansynchronen Verarbeitung von Queries zurecht kommt - Asynchronität kommt sowieso durch unterschiedliche Nutzeraktionen hinein, da kann deine Anwendung eh nicht komplett linear ablaufen.

    Wenn die Übersichtlichkeit dabei für dich zum Problem wird, dann schreibe dir einen Wrapper, der das komplette Handling einer solchen Anfrage (woher immer sie auch kommt) übernimmt, und nicht nur die Datenselektion per Query an die WebDatabase allein.

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
  3. Laut HTML WebDatabase [w3.org] ist ein synchroner Zugriff vorgesehen, wird aber z.B. von Google Chrome nicht unterstützt.

    Wenn es nur möglich ist, solltest du asynchronen Zugriff verwenden! Synchroner Zugriff macht die Sache nur langsam und dadurch nicht berechenbarer. Jegliches Input/Output in JS ist asynchron - und das ist eigentlich auch gut so.

    Was funktioniert, ist der asynchrone Zugriff, der die Programmierung (in meinen Augen) bei vielen Queries schnell komplett unübersichtlich macht.
    Auch ist ein fester Programmablauf extrem schwer zu kontrollieren.

    Das ist wohl Übungs- und Gewöhnungssache. Was genau hast du vor? Dein Beispiel ist nicht komplex. Es ist synchroner viel komplexer, weil du das Unmögliche möglich machen willst. Einfache SELECTs sind asynchron recht einfach zu lösen. Der Programmablauf ist zudem determiniert. In der Reihenfolge, in der du die DB-Befehle ausführst, werden auch die Antwort-Callback aufgerufen.

    Klar, wenn du viele hintereinandergeschaltete Operationen hast (SELECT, dann ggf. auf jedem Eintrag ein UPDATE, bei dessen Erfolg eine Änderung der Anzeige), dann ist die Callback-Schachtelung entsprechend komplex. Das ist allerdings eine Frage der sinnvollen Strukturierung des Programms und übersichtlichen Aufteilung in Funktionen.

    Das alert() hält also offensichtlich die Ausführung der Funktion querySync() an, nicht aber die Ausführung des Callbacks, welches dann die Variable this.result ersetzen kann.

    Richtig - JavaScript ist streng single-threaded, es wird immer nur eine Funktion gleichzeitig ausgeführt. Wenn ein JavaScript läuft, dann kann nicht gleichzeitig im Hintergrund eine andere ausgeführt werden (Ausnahme: Web Workers).

    Jegliche »wait«-Funktionen in JavaScript sind daher Quatsch. Man kann in JS nicht aktiv »nichts tun«, bis eine andere Funktion ausgeführt wird, denn die wartende Funktion wird erst dann ausgeführt, wenn der Interpreter zur Ruhe kommt und die aktuelle Funktion sich beendet. »Besseres« Warten mit setTimeout ist auch immer asynchron, d.h. mit Callbacks. Die werden ausgeführt, wenn der Interpreter keine anstehenden Funktionsaufrufe mehr abzuarbeiten hat. Es gibt also nur eine »Ausführungs-Warteschleife«, kein paralleles Ausführen.

    Sieht jemand von Euch eine Möglichkeit das Problem zu lösen?

    Ja: Verstehe die funktionale und asynchrone Natur von JavaScript. Dann kannst du dir ziemlich einfach und schnell brauchbare Helferfunktionen schreiben. Der übergibst du dann eine Callback-Funktion (z.b. einen Funktionsausdruck oder eine Funktion über ihren Namen):

    dbquery('SELECT name FROM tabelle WHERE id = 115;', function (transaction, results) {  
       alert(results);  
    });  
      
    function dbquery(query, parameters, callback){  
       db.transaction(function (transaction) {  
          transaction.executeSql(query, parameters, callback, function (e) {  
             alert('SQL-Error in Query "' + q + '"\r\nError Message: ' + e.message);  
          });  
       });  
    }
    

    Wozu genau meinst du unbedingt synchronen Zugriff zu brauchen? Wie gesagt, weil JavaScript so funktioniert, wie es funktioniert, wird es unübersichtlicher, schwieriger und letztlich unmöglich sein, Synchronizität vorzutäuschen.

    Mathias