Как правилно да извлека всички данни от 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. Във вашето обратно извикване на курсора onsuccess изглежда, че не придвижвате курсора след първия запис. Трябва да добавите 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 = обратно извикване; -- във функцията addparsedData -- Какво е обратното извикване? Знам какво е функция за обратно извикване, но говоря за екземпляра във вашия пример, къде е деклариран? - person Ebad Saghar; 15.11.2014
comment
кодът във вашия пример работи (за мен), след като направих малка корекция: във функцията getAll.onsuccess..... var cursor = event.target.result трябва да бъде var cursor = getAll.result || event.target.result. курсорът излизаше като недефиниран (отново за мен), преди да направя тази корекция. Но независимо от това, работи - благодаря. - person Ebad Saghar; 15.11.2014
comment
Обратното извикване е вторият аргумент на функцията addParsedData. Това е само пример за това как да разделите къде пишете код. Например, ако искате нещо да се случи след като вмъкванията са напълно завършени, тогава ще поставите това във функция и ще предадете тази функция като 2-ри аргумент. - 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