Sto lavorando su un po 'di JavaScript che interagisce con un database SQLite lato client, tramite il nuovo window.openDatabase(...)
, database.transaction(...)
e API correlate. Come molti di voi sanno quando si esegue una query in questo modo è una chiamata asincrona, che è in genere buona. È possibile effettuare la chiamata e gestire i risultati in modo appropriato con i callback.Query sincrona al database SQL Web
Nella mia situazione attuale sto lavorando ad un algo per un client che fa una gerarchia che cammina nel database memorizzato localmente. La parte dell'algo con cui ho problemi richiede di iniziare da una riga, che ha un riferimento a un "genitore" (da id) che è un'altra riga più in alto nella tabella. Devo continuare a camminare su quest'albero fino a raggiungere la radice.
Il problema è che sono in un punto in cui non sono sicuro di come utilizzare una query di stile asincrona con un callback per continuare a fornire gli id padre del ciclo. Idealmente potrei ottenere il blocco della query in modo che possa fare tutto nel ciclo. Ecco le parti principali della mia configurazione attuale:
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;
}
}
Come si può immaginare, non funziona bene. hierarchyArr ottiene un "indefinito" inserito in esso, e quindi lo script si blocca quando tenta di verificare il tipo di rs [0].
Quando provo a configurarlo con un callback (db.getRSAndCallback(sql, callbackFunc)
, che ho usato per le query precedenti, non interdipendenti, va benissimo) è peggio: il ciclo interno decolla come un matto perché l'ID non viene aggiornato; presumibilmente perché il loop mantiene l'interprete JavaScript così occupato da non riempire mai effettivamente lo rs
. In alcuni test artificiali in cui ho forzato il ciclo interno a rompere dopo alcune iterazioni tutte le callback hanno iniziato a passare tutte alla fine, dopo che il ciclo è terminato.
Lo "standard" (come è adesso) a http://dev.w3.org/html5/webdatabase/#synchronous-database-api sembra indicare che c'è un'API sincrona, ma non ho visto alcun segno su alcun browser basato su WebKit.
Qualcuno può offrire suggerimenti su come potrei o, a. formulare correttamente queste query iterative e interdipendenti usando i callback o, b. in qualche modo ottenere la chiamata per effettivamente accadere in modo sincrono o apparentemente sincrono.
Mille grazie in anticipo per chiunque faccia una pausa a questo piccolo problema apparentemente insidioso.
Naim
P.S. Ecco implementazione del cliente di db.getRS
per riferimento:
.
.
.
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;
},
.
.
.
Oh, ho anche voluto citare: Se sto debug il copione e ho impostato un diritto punto di interruzione su ' hierarchyArr.push (rs [0]); 'lo script funziona bene. Passando attraverso di esso, il recordset viene popolato e l'id viene aggiornato e percorre la gerarchia. Disabilitare il punto di interruzione e lasciarlo funzionare e si blocca dove ho menzionato sopra, senza dubbio perché la pausa nell'esecuzione corrente consente di terminare la query. – Naim