13

newishおよび関連する APIwindow.openDatabase(...)を介して、クライアント側の SQLite データベースと対話する JavaScript のビットに取り組んでいます。database.transaction(...)ほとんどの人が知っているように、この方法でクエリを実行すると、それは非同期呼び出しであり、通常は適切です。コールバックを使用して、呼び出しを行い、必要に応じて結果を処理できます。

私の現在の状況では、ローカルに保存されたデータベースでいくつかの階層を歩くクライアントのアルゴに取り組んでいます。私が問題を抱えているアルゴの部分は、テーブルのさらに上の別の行である「親」(IDによる)への参照を持つ行から開始する必要があります。根にたどり着くまで、この木を歩き続けなければなりません。

問題は、コールバックで非同期スタイルのクエリを使用してループの親 ID をフィードし続ける方法がわからないところにいることです。理想的には、ループ内ですべてを実行できるように、クエリをブロックすることができます。現在のセットアップの重要な部分は次のとおりです。

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

ご想像のとおり、うまくいきません。hierarchyArr に「未定義」がプッシュされ、スクリプトが rs[0] のタイプをチェックしようとするとクラッシュします。

コールバックを使用して設定しようとすると ( db.getRSAndCallback(sql, callbackFunc)、以前の非相互依存クエリに使用したのは問題ありません)、さらに悪いことです。ID が更新されないため、内側のループが狂ったように離陸します。おそらく、ループによって JavaScript インタープリターがビジー状態に保たれているため、実際にはいっぱいにならないからrsです。いくつかの人工的なテストでは、ループが終了した後、いくつかの反復後にすべてのコールバックがすべて通過し始めました。

http://dev.w3.org/html5/webdatabase/#synchronous-database-apiの「標準」(現在のような)は、同期 API があることを示しているようですが、私は何も見ていません。 WebKit ベースのブラウザーで署名します。

誰かが私がどのようにできるかについて提案を提供できますか?コールバックを使用して、これらの反復的で相互に依存するクエリを適切に作成するか、または b. どうにかして、呼び出しを実際に同期または明らかに同期して行うようにします。

この一見トリッキーな小さな問題を解いてくれた人に、前もって感謝します。

ナイム

db.getRSPS参照用のクライアントの実装は次のとおりです。

.
.
.
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;
},
.
.
.
4

2 に答える 2

10

同様の問題を解決するためにコールバックとクロージャーを使用しました。

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

この例の続きでは、フォルダーには、他のフォルダーとの関係を定義するための親プロパティがあります。ドキュメントも同様です。以下は、クロージャー ( success )を使用してドキュメントのパスを取得します。

  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);
  }
于 2011-01-09T10:06:32.123 に答える
1

残りのクエリのスタックへのクロージャーでコールバックを使用できます。または、再帰を使用して、スタックをパラメーターとして渡すこともできます。

于 2010-10-11T03:41:51.150 に答える