Pregunta

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 window.openDatabase(...) newish, database.transaction(...) y las API relacionadas. Como la mayoría de ustedes saben cuando se ejecuta una consulta de esta manera se trata de una llamada asincrónica, que suele ser buena. Usted puede hacer la llamada y manejar los resultados según el caso, con las devoluciones de llamada.

En mi situación actual que estoy trabajando en un algo para un cliente que hace alguna jerarquía caminar en la base de datos almacenada localmente. La parte del algo que estoy teniendo problemas con requiere empezar en algún fila, que tiene una referencia a un "padre" (por id) que es otra fila más arriba en la tabla. Tengo que seguir caminando hasta este árbol hasta llegar a la raíz.

El problema es que estoy en un punto donde no estoy seguro de cómo utilizar una consulta de estilo asíncrona con una devolución de llamada a mantener la alimentación de los identificadores de los padres bucle. Lo ideal sería que pudiera conseguir la consulta para bloquear de modo que pueda hacerlo todo en el bucle. Aquí están las piezas 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, que no funciona bien. hierarchyArr recibe un "indefinido" empujados a ella, y luego la secuencia de comandos se bloquea cuando se trata de comprobar 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 solo interdependientes finas) es peor: el bucle interior despega como loco porque ID no está siendo actualizado; presumiblemente porque el bucle es mantener el intérprete de JavaScript tan ocupado que en realidad nunca se llena rs. En algunas pruebas artificial donde Forcé el bucle interno de romper después de unas pocas iteraciones todas las devoluciones de llamada empezaron a venir a través de todos al final, después de que el bucle termina.

El "estándar" (tal como es en este momento) 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 él en ningún navegadores basados ??en WebKit <. / p>

¿Alguien puede ofrecer sugerencias sobre cómo puede ser que sea, a. adecuadamente formular estas consultas iterativas e interdependientes utilizando las devoluciones de llamada o, b. de alguna manera obtener la llamada a suceder en realidad de una manera sincrónica o aparentemente sincrónica.

Muchas gracias de antemano para cualquier persona que tiene una grieta en este pequeño problema aparentemente complicado.

Naim

P.S. Aquí está la implementación del cliente de db.getRS de 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;
},
.
.
.
¿Fue útil?

Solución

utiliza devoluciones de llamada y un cierre para resolver un problema similar, tenga en cuenta:

function getFolder(id, callback) {
var data = [];
ldb.transaction(function (tx) {
tx.executeSql('SELECT * FROM folders where id=?',
    [id],
    function (tx, results) {
        if (results.rows && results.rows.length) {
            for (i = 0; i < results.rows.length; i++) {
                data.push(results.rows.item(i));
            }
        }
        if (typeof(callback) == 'function')
            callback(data);
    },
    function (tx, error) {
        console.log(error);
    });
});
}

En la continuación de este ejemplo, la carpeta tiene una propiedad padres para definirlo de relación con otras carpetas. Al igual que un documento. A continuación se le dará el camino de un documento mediante un cierre ( ):

  function getDocPath(doc, callback) {
      var path = [];
      var parent = doc.parent;
      var success = function(folder) {
         var folder = folder[0];
         parent = folder.parent;
         path.push({'id':folder.id,'name':folder.name});
         if (parent != "undefined")
             getFolder(parent, success);
         else
             if ( typeof(callback) == 'function' ) callback(path.reverse());
      }
      getFolder(parent, success);
  }

Otros consejos

Se podría utilizar devoluciones de llamada con un cierre a su pila de consultas restantes. O puede utilizar la recursividad, pasando la pila como parámetros.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top