Сбит с толку индексированным удалением базы данных

Мой сценарий:

У меня есть проиндексированная страница базы данных db, которая извлекает несколько файлов (изображений) с кнопкой «удалить файл» рядом с каждым изображением. Кроме того, рядом с каждым изображением есть флажки для нескольких файлов, которые необходимо удалить. Кнопка «Удалить файл» вызывает функцию «удалить запись» и передает ей ключ... она отлично удаляет файл. Однако, когда кнопка массового удаления вызывает эту же функцию «deleteRecord» для массового удаления и передает ей ключ, никакие файлы не удаляются. 'deleteRecord' проходит через каждый ключ и имеет событие onsuccess. Однако ничего не удаляется?

Функция deleteFile (работает с отдельными кнопками):

function deleteRecord (id) {
    console.log('inside deleteRecord.  id: ' + id);
    var transaction = db.transaction("patient", "readwrite");
    var objectStore = transaction.objectStore("patient");
    var request = objectStore.delete(id);
    request.onsuccess = function(evt) {
    console.log("It's gone!");
};

Он успешно вызывается из:

inputBttn.onclick = function () {
    var prompt = 'Are you sure you want to delete this record?'
    answer = confirm(prompt);
    if (answer) {
    deleteRecord(key);
    console.log('Key = ' + key + ' Record Deleted');
}

и безуспешно из:

function massDelete() {
    console.log('inside massDelete');
    var checkboxes = document.getElementsByName('c1');                  
    var prompt = 'You are about to delete Multiple Records.  Are you sure?'
    var answer = confirm(prompt);
    if (answer) {
    console.log('Delete confirmed...starting mass delete');
    for (var x = 0; x < checkboxes.length; x++) {
        if (checkboxes[x].checked) {
        var key = checkboxes[x].value;
        console.log('checkbox value = ' + key);
        deleteRecord (key);
    }
};

Буду очень признателен за любые объяснения, почему это происходит.


person Phatman    schedule 22.12.2012    source источник
comment
У вас это сработало? Ваши идентификаторы строки или числа? Идентификаторы, используемые для .delete(id), должны соответствовать типу, используемому для создания идентификаторов.   -  person user1460015    schedule 31.01.2013


Ответы (5)


Я долго искал ответ на этот вопрос, попробовав здесь код, который, что интересно, не помечен как решение. Ответ Чжо Туна мне не помог, но дал мне несколько идей. Итак, несмотря на то, что это старая ветка, я опубликую полное решение, которое действительно работает, поскольку я не смог найти в Интернете ничего, что решило бы эту довольно распространенную проблему. Мое решение находится в магистрали, поэтому есть небольшой контекст (в основном ссылка this), который можно легко проигнорировать:

deleteFromDb: function(keys, callback) {
    var _this = this,
        request = indexedDB.open(_this.LOCAL_DB, _this.DB_VERSION);

    request.onsuccess = function(event) {
        var db = event.target.result,
            tx = db.transaction([_this.URL_TABLE], "readwrite"),
            store = tx.objectStore(_this.URL_TABLE),
            recursiveDelete;

        recursiveDelete = function(_index) {
            var deleteRequest;

            // base case
            if (_index >= keys.length) {
                callback();
                return;
            }   
            deleteRequest = store.delete(keys[_index]);
            deleteRequest.onsuccess = function(event) {
                recursiveDelete(_index + 1); 
            }   
        }   
        recursiveDelete(0);
    }   
}
person Marshall Farrier    schedule 18.10.2013

Я не вижу ничего явно плохого в коде. Некоторые предложения:

  1. В deleteRecord добавьте обработчик транзакции для событий завершения и отмены, посмотрите, какой из них сработает:

    transaction.onabort = function(e) { console.log("abort"); };
    transaction.oncomplete = function(e) { console.log("complete"); };
    
  2. В deleteRecord отсутствует закрывающая фигурная скобка, поэтому, вероятно, это не тот код, с которым вы работаете. Если у вас возникнут дополнительные проблемы, рассмотрите возможность загрузки сокращенной версии вашего кода в jsfiddle.

  3. В каких браузерах вы это пробовали? Все ли они демонстрируют одинаковое поведение?

Редактировать: Откуда key в inputBttn.onclick? Вы уверены, что massDelete передает правильное значение deleteRecord?

person dgrogan    schedule 22.12.2012
comment
К сожалению, я могу использовать эту программу только в Chrome. API, которые создают базу данных и фотографии, на данный момент поддерживаются только Chrome. - person Phatman; 29.12.2012

Код выглядит нормально, однако я избегаю асинхронного цикла:

function deleteRecords (ids) {    
  var transaction = db.transaction("patient", "readwrite");
  var objectStore = transaction.objectStore("patient");
  var id = ids.shift();
  var request = objectStore.delete(id);
  request.onsuccess = function(evt) {
    console.log(id + " deleted");
    if (ids.length > 0) {
      id = ids.shift();
      objectStore.delete(id);
    }
  }
  request.onerror = function(evt) {
    console.log(id + " delete fail");
  }
};
person Kyaw Tun    schedule 23.12.2012

Согласно MDN, хранилище объектов может иметь только одну открытую транзакцию «чтение/запись» в любой момент времени. Цикл будет пытаться открыть несколько транзакций «чтение/запись» друг над другом, что, вероятно, приведет к сбою. Я предполагаю, что такое же ограничение присутствует в Chrome. Решение Kyaw Tun должно работать для предотвращения множественных транзакций «чтение/запись», хотя вам не нужно будет повторно открывать транзакции.

Ссылка на справку по MDN IDBTransaction

person Jared    schedule 06.08.2013

  1. При попытке удалить несколько записей убедитесь, что транзакция остается активной. В отношении этого ответа Маршалла является правильным.
  2. Еще одна проблема, с которой я столкнулся при удалении записей, заключалась в определении того, является ли ключ числовым или строковым. Если вы используете неверный тип ключа, запись может не быть удалена.
person Ashish    schedule 10.01.2015