транзакция indexedDB openCursor при успехе возвращает пустой массив

            req = db.openCursor();
            req.customerData=new Array() //[{a:1}]
            req.onsuccess = function(e) {
                var cursor = e.currentTarget.result;
                if (cursor) {
                    //console.log(cursor.value);
                    e.currentTarget.customerData.push(cursor.value);
                    e.currentTarget.customerData.push("hello?");         
                    cursor.continue()
                }
                else {
                    console.log(e.currentTarget.customerData) //this always correct
                }
            }

     console.log(req.customerData); //outside the onsuccess everything is gone?

console.log(req);

Я вижу клиентские данные, когда открываю объект в консоли Chrome.

console.log(req.customerData);

Но когда я делаю выше, он пуст?

замена new Array() на [{a:1}]

console.log(req.customerData);

Я вижу a, а также другие объекты

но потом снова

console.log(req.customerData[0].a);

работает, а другие объекты исчезли.

Как я могу сохранить данные клиента? Я пытался просто нажимать цифры или текст, но после завершения транзакции то же самое. Я не могу получить данные, отображать их только в console.log() во время транзакции?

Я знаю, что это должно быть что-то прошедшее по ссылке, но каждая переменная, которую я ввожу, исчезает?

Добавлен полный пример ниже, просто введите write() и read() в консоли

    <script>
        var iDB
        ready=function(){
            var request = indexedDB.open("my-database",1);
            request.onupgradeneeded = function(e) {
                var db = e.currentTarget.result
                var store = db.createObjectStore("store", {keyPath: "muts", autoIncrement:false})
                //store.createIndex("by_submit", "submit", {unique: false})
                console.log('db upgrade', 'v'+db.version)
            }
            request.onerror = function(e) {
                //var db = e.currentTarget.result;
                //db.close()
                console.error('db error ',e)
            }
            request.onsuccess = function(e) {
                var db = e.currentTarget.result
                db.onversionchange = function(e) {
                    db.close()
                    console.log('db changed', 'v'+db.version, 'CLOSED')
                }
                console.log('db setup', 'v'+db.version, 'OK')
            }
            iDB=request
        }

        drop=function(){
            iDB.result.close()
            var req = indexedDB.deleteDatabase(this.iDB.result.name);
            req.onsuccess = function() {console.log("Deleted database successfully")}
            req.onerror = function() {console.log("Couldn't delete database")}
            req.onblocked = function() {console.log("Couldn't delete database due to the operation being blocked")}
        }

        read=function(){
            var db=iDB
                    .result
                    .transaction(["store"], "readwrite").objectStore("store");

            var req = db.openCursor();
            req.iData=new Array();
            req.onsuccess = function(e) {
                var cursor = e.currentTarget.result;
                if (cursor) {
                    e.currentTarget.iData.push(cursor.value);
                    e.currentTarget.iData.push("hello");
                    cursor.continue()
                }
                else {
                    console.log(e.currentTarget.iData)
                }
            }

            console.log(req.iData)

        }

        write=function(){
            var db=document.querySelector('my\-database')
                .iDB
                .result
                .transaction(["store"], "readwrite").objectStore("store");

            var customerData = [
                {muts: "Bill", qty: "1"},
                {muts: "Donna", qty: "1"}
            ]

            for (var i in customerData){db.put(customerData[i])}
        }

        ready()
    </script>

person Gert Cuykens    schedule 30.09.2014    source источник
comment
Глупый вопрос, а зачем вы записываете данные обратно в объект запроса? Почему бы не использовать свой собственный массив? Я склонен рассматривать такие объекты запроса как только для чтения (даже если это не так).   -  person Raymond Camden    schedule 30.09.2014
comment
Я был в отчаянии, ха-ха :) Перепробовал все, чтобы вынести его в отдельный массив. Мне просто нужна переменная, в которой есть данные после завершения курсора.   -  person Gert Cuykens    schedule 30.09.2014


Ответы (1)


Несколько вещей

  • Я рекомендую не устанавливать пользовательские свойства объекта IDBRequest. Вместо этого создавайте и получайте доступ к объектам, которые находятся во внешней области.
  • Нет необходимости использовать event.currentTarget. event.target достаточно (как и «это», так и сам объект запроса).
  • onversionchange устарел.
  • Из-за асинхронной природы indexedDB вы можете пытаться вывести на консоль что-то, чего еще не существует или больше не существует. Вместо этого попробуйте распечатать что-нибудь после завершения транзакции.

Например:

function populateArray(openDatabaseHandle, onCompleteCallbackFunction) {
  var transaction = openDatabaseHandle.transaction('store');
  var store = transaction.objectStore('store');
  var myArray = [];
  var request = store.openCursor();
  request.onsuccess = function() {
    var cursor = this.result;
    if(!cursor) return;
    myArray.push(cursor.value);
    cursor.continue();
  };
  transaction.oncomplete = function() {
    onCompleteCallbackFunction(myArray);
  };
}

// An example of calling the above function
var conn = indexedDB.open(...);
conn.onsuccess = function() {
  populateArray(this.result, onPopulated);
};

// An example of a callback function that can be passed to 
// the populateArray function above
function onPopulated(data) {
  console.debug(data);
  data.forEach(function(obj) {
    console.debug('Object: %o', obj);
  });
}
person Josh    schedule 30.09.2014
comment
Я вернусь к этому, сначала нужно провести несколько тестов, чтобы сравнить разницу. - person Gert Cuykens; 30.09.2014
comment
Хорошо, ключевая часть действительно заключается в том, что область, в которой я могу использовать данные, находится в oncomplete том же принципе, что и onload для ajax. - person Gert Cuykens; 01.10.2014
comment
Будет ли создание объекта массива всего содержимого во внешней области потенциально увеличивать объем памяти? Разве это не дублирование БД? Можно ли получить доступ к самому курсору из того места, где он был вызван? - person Vass; 07.07.2021