Question

Je travaille sur un peu de JavaScript qui interagit avec une base de données SQLite côté client, via le window.openDatabase(...) Newish, database.transaction(...) et API connexes. Comme vous le savez quand vous exécutez une requête de cette manière, il est un appel asynchrone, ce qui est généralement bon. Vous pouvez faire l'appel et de gérer les résultats selon le cas avec callbacks.

Dans ma situation actuelle, je travaille sur un algo pour un client qui fait un peu de marche de la hiérarchie dans la base de données stockées localement. La partie de l'algo que je vais avoir du mal à commencer nécessite à un rang, qui a une référence à un « parent » (par id) qui est une autre ligne plus haut dans le tableau. Je dois continuer à marcher jusqu'à cet arbre jusqu'à atteindre la racine.

Le problème est que je suis à un point où je ne suis pas sûr de savoir comment utiliser une requête de type asynchrone avec un rappel pour continuer à nourrir les ids parents en boucle. Idéalement, je pouvais obtenir la requête pour bloquer afin que je puisse le faire tout dans la boucle. Voici les éléments clés de ma configuration actuelle:

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

Comme vous pouvez l'imaginer, il ne fonctionne pas bien. hierarchyArr obtient un « non défini » poussé dans, puis se bloque le script quand il essaie de vérifier le type de rs [0].

Lorsque je tente de le configurer avec un rappel (db.getRSAndCallback(sql, callbackFunc), que j'ai utilisé pour les requêtes antérieures, non interdépendantes très bien), il est pire: la boucle intérieure prend son envol comme un fou parce que id ne reçoit pas mis à jour; sans doute parce que la boucle est de garder l'interpréteur JavaScript tellement occupé qu'il ne remplit réellement rs. Dans certains tests artificiels où je forcé la boucle intérieure pour briser après quelques itérations tous les callbacks ont commencé à venir à travers tout à la fin, après la boucle terminée.

Le "standard" (tel qu'il est en ce moment) http : //dev.w3.org/html5/webdatabase/#synchronous-database-api semble indiquer qu'il existe une API synchrone, mais je n'ai pas vu aucun signe de celui-ci sur tous les navigateurs basés sur Webkit <. / p>

Quelqu'un peut-il offrir des suggestions sur la façon dont je pourrais soit, a. formuler correctement ces requêtes itératives, interdépendantes utilisant callbacks ou, b. obtenir en quelque sorte l'appel arrive effectivement d'une manière synchrone ou apparemment synchrone.

Un grand merci à l'avance pour toute personne qui prend une fissure à ce petit problème apparemment délicat.

Naim

P.S. Voici la mise en œuvre de db.getRS de référence du client:

.
.
.
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;
},
.
.
.
Était-ce utile?

La solution

J'utilisé callbacks et une fermeture pour résoudre un problème similaire, pensez à:

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

Dans la suite de cet exemple, le dossier a une propriété parent pour définir sa relation avec d'autres dossiers. Comme le fait un document. Ce qui suit vous obtiendrez le chemin d'un document à l'aide d'une fermeture ( succès ):

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

Autres conseils

Vous pouvez utiliser les callbacks avec une fermeture à votre pile de requêtes restantes. Ou vous pouvez utiliser récursion, en passant la pile en tant que paramètres.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top