Как правильно получить все данные из IndexedDb в приложении WinJS для Windows 8?

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

Вот как выглядит мой код до сих пор:

var request = window.indexedDB.open("List", 1);
request.onsuccess = function (event) {
                db = request.result;
                console.log("success: " + db);
            };

request.onupgradeneeded = function (event) {
     db = event.target.result;
     var objectStore = db.createObjectStore("List", { keyPath: "id" });
     for (var i in parsedData) {
          objectStore.add(parsedData[i]);
     }

     console.log("RETRIEVING DATA");
     var transaction = request.transaction("List");
     var store = transaction.objectStore("List");
     store.openCursor().onsuccess = function (e) {
         var cursor = e.target.request;
         if (cursor) {
             console.log("List NAMES == " + cursor.value.Name);
         }
     }

}

Теперь есть пара вещей, которые нужно сказать об этом коде, который я написал. Прежде всего, я знаю, что получение информации должно быть отдельной функцией (я просто написал это только для целей печати/регистрации). Во-вторых, по какой-то причине «ПОИСК ДАННЫХ» должен как минимум печатать в журнал, но этого не происходит, и я не знаю, почему. В-третьих, и самое главное, я продолжаю получать сообщение об ошибке в этой строке:

var transaction = request.transaction("List");

Ошибка: JavaScript runtime error: Function expected

Не уверен, что вызывает эти 2 проблемы, которые у меня возникают.


person Ebad Saghar    schedule 14.11.2014    source источник


Ответы (2)


  1. Обратный вызов onupgradeneeded вызывается только тогда, когда вы увеличиваете параметр версии до indexedDB.open. Вам нужно будет увеличивать, сохранять, а затем перезагружать каждый раз, когда вы хотите, чтобы ваш код примера выполнялся. Это должно привести к печати команды RETRIEVING DATA. Было бы намного проще протестировать, если бы вы не пытались вставлять/считывать данные в функции обратного вызова onupgradeneeded. Таким образом, вам не нужно будет увеличивать версию базы данных каждый раз, когда вы хотите протестировать/запустить код.
  2. Вам нужно открыть транзакцию, используя объект базы данных. Прямо сейчас вы заявляете var transaction = request.transaction('List');. запрос является IDBRequest. Я не думаю, что есть метод IDBRequest.prototype.transaction. То, что вы хотите использовать, это IDBDatabase.prototype.transaction. Например, var transaction = db.transaction('List');.
  3. В качестве альтернативы № 2, но более сложной, вы можете использовать неявную транзакцию, которая используется как часть onupgradeneeded. Это специальная транзакция типа VERSION_CHANGE, автоматически созданная indexedDB, которая действительна только в теле обратного вызова onupgradeneeded. VERSION_CHANGE txs поддерживает чтение/запись. Если вы действительно хотите это сделать, вы можете использовать var transaction = event.target.transaction;. Я бы не рекомендовал это, но это возможно.
  4. В вашем обратном вызове курсора при успехе похоже, что вы не продвигаете курсор за первую запись. Вам нужно добавить cursor.continue(); в блок if, чтобы продолжить итерацию.

Простой пример того, как избежать необходимости каждый раз обновлять базу данных:

function upgradeDatabase(event) {
  var db = event.target.result;
  db.createObjectStore('List', { keyPath: "id" });
}

function addParsedData(parsedData, callback) {
  var request = indexedDB.open('List', 1);
  request.onupgradeneeded = upgradeDatabase;
  request.onsuccess = function(event) {
    var db = event.target.result;
    var tx = db.transaction('List','readwrite');
    tx.oncomplete = callback;
    var list = tx.objectStore('List');
    for(var i in parsedData) {
      list.add(parsedData[i]);
    }
  };
}

function retrieve() {
  var request = indexedDB.open('List', 1);
  request.onupgradeneeded = upgradeDatabase;
  request.onsuccess = function(event) {
    var db = event.target.result;
    var tx = db.transaction('List');
    var list = tx.objectStore('List');
    var getAll = list.openCursor();
    var items = [];
    tx.oncomplete = function() {
      console.log('Got items %o', items);
    };
    getAll.onsuccess = function(event) {
      var cursor = event.target.result;
      if(!cursor) return;
      items.push(cursor.value);
      cursor.continue();
    };
  };
}

// This would connect, create, insert, and then select
addParsedData(parsedData, retrieve);
person Josh    schedule 14.11.2014
comment
есть ли способ автоматически увеличить версию базы данных самостоятельно? Как или когда мне вручную изменить эту 1 на 2 или что-то еще? - person Ebad Saghar; 14.11.2014
comment
Придется ли мне менять версию каждый раз, когда я вставляю что-то новое?? - person Ebad Saghar; 14.11.2014
comment
Нет встроенного в indexedDB способа автоматического увеличения. Ничто не мешает вам использовать хак localStorage. Вместо этого я бы предложил использовать шаблоны, продвигаемые разработчиками indexedDB, где вы просто выполняете другие запросы без обновления базы данных, если схема не изменилась. Вам не нужно менять версию, чтобы вставить что-то новое. - person Josh; 15.11.2014
comment
строка tx.oncomplete = callback; -- в функции addparsedData -- Что такое обратный вызов? Я знаю, что такое функция обратного вызова, но я говорю об экземпляре в вашем примере, где он объявлен? - person Ebad Saghar; 15.11.2014
comment
код в вашем примере работал (для меня) после того, как я сделал небольшое исправление: в функции getAll.onsuccess..... var курсор = event.target.result должен быть var курсор = getAll.result || событие.цель.результат. курсор выходил как неопределенный (опять же, для меня) до внесения этого исправления. Но тем не менее, это работает - спасибо. - person Ebad Saghar; 15.11.2014
comment
Обратный вызов — это второй аргумент функции addParsedData. Это просто пример того, как разделить место, где вы пишете код. Например, если вы хотите, чтобы что-то произошло после полного завершения вставки, вы должны поместить это в функцию и передать эту функцию в качестве второго аргумента. - person Josh; 15.11.2014
comment
В теле getAll.onsuccess = function(event) {...} все одно и то же: «event.target», «getAll» и «this». это неявно устанавливается как связанный контекст функции. Для event.target устанавливается значение getAll, когда js создает объект события для передачи функции. getAll — это просто имя переменной запроса. Это должно быть 100% идентичное поведение. - person Josh; 15.11.2014

Я не знаю, почему он не показывает console.log в вашем случае. Это не работает для меня с приведенным выше кодом, потому что у меня нет материала для parsedData, когда я комментирую это, я получаю журнал и ошибку, которую вы даете в транзакции.

Эта ошибка связана с тем, что вы не должны вызывать ее как функцию. Это уже открытая транзакция, и вы можете просто сделать это: request.transaction.objectStore("<Objectstore>"); для открытия магазина.

Так что это, вероятно, не решит вашу проблему с console.log, но должно исправить другую часть!

person Dick van den Brink    schedule 14.11.2014
comment
проанализированные данные - это просто объект JSON. - person Ebad Saghar; 14.11.2014
comment
Итак, у меня есть request.transaction.objectore('List'); -- Наконец-то я получаю журнал извлечения данных -- но я не получаю журнал в операторе if для печати значений. - person Ebad Saghar; 14.11.2014