Pracuję nad fragmentem JavaScript, który współdziała z bazą danych SQLite po stronie klienta, za pośrednictwem nowej wersji window.openDatabase(...)
, database.transaction(...)
i pokrewnych interfejsów API. Jak większość z was wie, kiedy wykonujemy zapytanie w ten sposób, jest to wywołanie asynchroniczne, które zwykle jest dobre. Możesz wykonać połączenie i obsłużyć wyniki odpowiednio w przypadku wywołań zwrotnych.Zapytanie synchroniczne do bazy danych Web SQL
W mojej obecnej sytuacji pracuję nad algo dla klienta, który wykonuje pewną hierarchię w lokalnie przechowywanej bazie danych. Część algo, z którą mam problem, wymaga rozpoczynania od pewnego wiersza, który ma odniesienie do "rodzica" (według id), który jest kolejnym rzędem dalej w tabeli. Muszę podchodzić do tego drzewa, aż dotrę do korzenia.
Problem polega na tym, że jestem w punkcie, w którym nie jestem pewien, jak użyć asynchronicznego zapytania stylu z wywołania zwrotnego, aby nadal podawać identyfikatory macierzyste pętli. Najlepiej byłoby, gdyby zapytanie zostało zablokowane, dzięki czemu mogę zrobić to wszystko w pętli. Oto kluczowe elementy mojej obecnej konfiguracji:
for (i in search.searchResults.resultsArray)
{
hierarchyArr = new Array();
pageHierarchyArr = new Array();
id = search.searchResults.resultsArray[i].ID;
while (id != null && id != "")
{
var hierarchySql = "SELECT ID, parentID, type, content FROM content WHERE ID = " + id;
// This is a prettied up call to database.transaction(...)
var rs = db.getRS(hierarchySql);
// Ideally the code below doesn't execute until rs is populated
hierarchyArr.push(rs[0]);
if (rs[0].type == "page")
{
pageHierarchyArr.push(rs[0]);
// Do some additional work
}
id = rs[0].parentID;
}
}
Jak można sobie wyobrazić, nie działa dobrze. hierarchyArr dostaje "undefined" wciśnięty do niego, a następnie skrypt ulega awarii, gdy próbuje sprawdzić typ rs [0].
Kiedy próbuję skonfigurować go za pomocą wywołania zwrotnego (db.getRSAndCallback(sql, callbackFunc)
, którego użyłem do wcześniejszych, niezwiązanych ze sobą zapytań), jest gorzej: wewnętrzna pętla startuje jak szalona, ponieważ id nie jest aktualizowany; prawdopodobnie dlatego, że pętla sprawia, że interpreter JavaScript jest tak zajęty, że nigdy nie wypełnia on w rzeczywistości rs
. W niektórych sztucznych testach, w których zmusiłem wewnętrzną pętlę do zerwania po kilku iteracjach, wszystkie połączenia zwrotne zaczęły przechodzić przez wszystkie na końcu, po zakończeniu pętli.
"Standardowy" (taki jak jest teraz) pod numerem http://dev.w3.org/html5/webdatabase/#synchronous-database-api wydaje się wskazywać, że istnieje synchroniczny interfejs API, ale nie widziałem żadnego znaku tego w przeglądarkach opartych na WebKit.
Czy ktoś może zaproponować, w jaki sposób mogę, a. właściwie sformułować te iteracyjne, współzależne zapytania za pomocą wywołań zwrotnych lub, b. w jakiś sposób uzyskać połączenie, aby rzeczywiście nastąpiło w sposób synchroniczny lub pozornie synchroniczny.
Bardzo dziękuję z góry każdemu, kto ma problem z tym pozornie trudnym problemem.
Naim
P.S. Oto implementacja klienta z db.getRS
dla odniesienia:
.
.
.
getRS: function(sql)
{
var output = [];
db.database.transaction(function(tx)
{
tx.executeSql(sql, [], function(tx,rs)
{
for(i = 0; i < rs.rows.length; i++)
{
output.push(rs.rows.item(i));
}
},
function(tx, error) { ... }
)});
return output;
},
.
.
.
Och, ja też chciałem wspomnieć: Jeśli mam debugowanie skryptu i ustawić breakpoint prawo na ' hierarchyArr.push (rs [0]); 'skrypt działa dobrze. Przechodząc przez to zestaw rekordów jest wypełniany, a identyfikator jest aktualizowany i przechodzi przez hierarchię. Wyłącz punkt przerwania i pozwól mu działać, a on zawiesza się w miejscu, o którym wspomniałem powyżej, bez wątpienia, ponieważ pauza w bieżącej realizacji umożliwia zakończenie zapytania. – Naim