Estoy trabajando en un poco de JavaScript que interactúa con una base de datos SQLite del lado del cliente, a través de la nueva window.openDatabase(...)
, database.transaction(...)
y API relacionadas. Como la mayoría de ustedes saben cuando ejecuta una consulta de esta manera, es una llamada asíncrona, que normalmente es buena. Puede hacer la llamada y manejar los resultados según corresponda con devoluciones de llamada.Consulta síncrona a la base de datos web SQL
En mi situación actual, estoy trabajando en un algo para un cliente que realiza una jerarquía caminando en la base de datos almacenada localmente. La parte del algo con el que estoy teniendo problemas requiere comenzar en una fila, que tiene una referencia a un "padre" (por id) que es otra fila más arriba en la tabla. Tengo que seguir caminando por este árbol hasta que llegue a la raíz.
El problema es que estoy en un punto en el que no estoy seguro de cómo usar una consulta de estilo asíncrono con una devolución de llamada para seguir alimentando los identificadores padre de bucle. Idealmente, podría hacer que la consulta se bloquee para que pueda hacerlo todo en el ciclo. Aquí están las partes clave de mi configuración actual:
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;
}
}
Como se puede imaginar, no funciona bien. hierarchyArr obtiene un "indefinido" insertado en él, y luego el script falla cuando intenta verificar el tipo de rs [0].
Cuando trato de configurarlo con una devolución de llamada (db.getRSAndCallback(sql, callbackFunc)
, que utilicé para las consultas anteriores, no interdependientes) es peor: el bucle interno despega como loco porque el id no se está actualizando; presumiblemente porque el bucle mantiene el intérprete de JavaScript tan ocupado que nunca llena realmente el rs
. En algunas pruebas artificiales en las que obligué al bucle interno a romperse después de algunas iteraciones, todas las devoluciones de llamada comenzaron a llegar al final, una vez finalizado el bucle.
El "estándar" (tal como está ahora) en http://dev.w3.org/html5/webdatabase/#synchronous-database-api parece indicar que hay una API síncrona, pero no he visto ninguna señal de ello en ningún navegador basado en WebKit.
¿Alguien puede ofrecer sugerencias sobre cómo podría, a. formular adecuadamente estas consultas iterativas e interdependientes utilizando devoluciones de llamada o, b. de alguna manera recibe la llamada para que realmente suceda de manera sincrónica o aparentemente sincrónica.
Muchas gracias de antemano para cualquier persona que tome una grieta en este pequeño problema aparentemente complicado.
Naim
P.S. Aquí está la implementación del cliente de db.getRS
para referencia:
.
.
.
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, yo también quería mencionar: Si estoy depurar el guión y me puse un punto de interrupción en la derecha ' hierarchyArr.push (rs [0]); 'el script funciona bien. Al recorrerlo, se llena el conjunto de registros y se actualiza la identificación, y recorre la jerarquía. Inhabilite el punto de interrupción y déjelo funcionar y se bloquea donde mencioné anteriormente, sin duda porque la pausa en la ejecución actual le permite finalizar la consulta. – Naim