Domanda

Sto lavorando su un po 'di JavaScript che interagisce con un database SQLite sul lato client, attraverso l'window.openDatabase(...) urrà, database.transaction(...) e le 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 a seconda dei casi con i callback.

Nella mia situazione attuale sto lavorando su un algo per un cliente che fa un po 'di gerarchia a piedi nel database memorizzato in locale. La parte del algo Ho problemi con richiede ad un qualche fila, che ha un riferimento a un "padre" (da id) che è un'altra riga più in alto nella tabella. Devo continuare a camminare su questo albero fino a raggiungere la radice.

Il problema è che sono a un punto in cui non sono sicuro di come utilizzare una query stile asincrono con un callback per continuare ad alimentare i ids ciclo genitore. Idealmente ho potuto ottenere la query per bloccare in modo che io possa fare tutto in loop. Ecco le parti principali della mia messa a punto corrente:

    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" spinto in esso, e quindi lo script si blocca quando tenta di controllare il tipo di rs [0].

Quando provo a configurarlo con un callback (db.getRSAndCallback(sql, callbackFunc), che ho usato per i precedenti, le query non interdipendenti bene) è peggio: il ciclo interno decolla come un matto perché id non è sempre aggiornata; presumibilmente perché il circuito è mantenere l'interprete JavaScript così occupato che non si è mai realmente riempie rs. In alcuni test artificiale forzai il ciclo interno di rompersi dopo poche iterazioni tutti i richiami iniziato che passa tutto alla fine, dopo il ciclo finito.

Il "standard" (come è adesso) a http : //dev.w3.org/html5/webdatabase/#synchronous-database-api sembra indicare che v'è un'API sincrono, ma non ho visto alcun segno di esso su tutti i browser basati su WebKit <. / p>

Qualcuno può offrire suggerimenti su come potrei neanche, a. correttamente formulare queste domande, interdipendenti iterative utilizzando callback o, b. in qualche modo ottenere la chiamata a effettivamente accadere in modo sincrono o apparentemente sincrono.

Molte grazie in anticipo per chi prende una crepa in questo piccolo problema apparentemente difficile.

Naim

P.S. Ecco implementazione del cliente di db.getRS di 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;
},
.
.
.
È stato utile?

Soluzione

ho usato callback e una chiusura per risolvere un problema simile, prendere in considerazione:

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);
    });
});
}

Nel proseguimento di questo esempio, la cartella ha una proprietà genitori per definire di relazione con altre cartelle. Come fa un documento. Di seguito ti porterà il percorso di un documento utilizzando una chiusura ( successo ):

  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);
  }

Altri suggerimenti

Si potrebbe usare callback con una chiusura al tuo stack di query rimanenti. Oppure si potrebbe usare la ricorsione, passando lo stack come parametri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top