Вопрос

Я работаю над небольшим количеством JavaScript, который взаимодействует с базой данных SQLite на стороне клиента через новое window.openDatabase(...), database.transaction(...) и связанные с ними API. Как большинство из вас знает, когда вы выполняете запрос таким образом, это асинхронный вызов, который обычно хорош. Вы можете сделать вызов и обрабатывать результаты в зависимости от обратных вызовов.

В моей нынешней ситуации я работаю над Algo для клиента, который проходит некоторую иерархию в локально сохраненной базе данных. Часть Algo у меня возникла проблема с требуемым начать с некоторой строки, которая имеет ссылку на «родительский» (по 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), который я использовал для более ранних, не взаимозависимых запросов просто отлично) Это хуже: внутренняя цикл вылетает как сумасшедший, потому что идентификатор не обновляется; предположительно, потому что цикл держит переводчик JavaScript так занят, что он никогда не заполняет rs. Анкет В некоторых искусственных испытаниях, где я заставил внутреннюю петлю прорваться после нескольких итераций, все обратные вызовы начали проходить через все в конце, после того, как петля закончилась.

«Стандарт» (например, он сейчас прямо сейчас) в http://dev.w3.org/html5/webdatabase/#synchronous-database-api Похоже, указывает, что существует синхронный API, но я не видел никаких признаков его ни в каких браузерах на основе Webkit.

Может кто-нибудь предложить предложения о том, как я могу либо. Правильно сформулируйте эти итеративные, взаимозависимые запросы, используя обратные вызовы или, б. как-то получить вызов на самом деле происходить в синхронном или видимо синхронному способу.

Заранее большое спасибо всем, кто примет трещину от этой, казалось бы, сложной маленькой проблемы.

Намель

PS Вот реализация клиента db.getRS Для справки:

.
.
.
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;
},
.
.
.
Это было полезно?

Решение

Я использовал обратные вызовы и закрытие, чтобы решить аналогичную проблему, рассмотрим:

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

В продолжении этого примера папка имеет свойство родительский Чтобы определить это отношение к другим папкам. Как и документ. Ниже примет ваш путь документа, используя закрытие (успех):

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

Другие советы

Вы можете использовать обратные вызовы с закрытием к стопке оставшихся запросов. Или вы можете использовать рекурсию, передавая стек в качестве параметров.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top