5

Загружайте данные и храните их в базе данных indexeddb. Периодически я имею сбои базы данных и потерял доступ к ней. Дайте мне, пожалуйста, решение, как использовать indexeddb асинхронно!Как работать с IndexedDB асинхронно?

Пример кода, который я использую сейчас:

var dataTotal = 0; 
var threads = 6; 

//openIndexeddbConnection(); 

function start(total){ 

dataTotal = total; 
    for (var i = 0; i < threads; i++) { 
    loadData(i); 
    } 
} 

function loadData(dataNum){ 
    var dataNext = dataNum + threads; 
    if(dataNext > dataTotal){ 
    //checkEnd(); 
    return; 
    } 

    $.ajax({ 
    url: baseUrl, 
    data: {offset: dataNum}, 
    success: function (data) { 
     successData(dataNext, data); 
    }, 
    type: 'GET' 
    }); 
} 

function successData(dataNext, data){ 
    var dataArray = data.split(';'); 

    saveData(dataArray); 

    loadData(dataNext); 
} 

function saveData(dataArray){ 

    putItem(); 
    function putItem(i) { 
    var count = i || 0; 
    if(dataArray.length <= i){ 
     return; 
    } 

    var transaction = Indexeddb.transaction([dataTableName], "readwrite"); 
    transaction.onsuccess = function (event) { 
     //continue 
     putItem(count); 
    }; 
    var objectStore = transaction.objectStore(dataTableName); 

    var request = objectStore.add({data: dataArray[count++]}); 
    } 
} 

ответ

3

Вы можете использовать обещания загружать и сохранять данные асинхронно IndexedDB. Вот две примерные функции для загрузки и сохранения данных в простой объект-хранилище в indexedDB.

Асинхронная загрузка из IndexedDB:

function loadFromIndexedDB(storeName, id){ 
 
    return new Promise(
 
    function(resolve, reject) { 
 
     var dbRequest = indexedDB.open(storeName); 
 

 
     dbRequest.onerror = function(event) { 
 
     reject(Error("Error text")); 
 
     }; 
 

 
     dbRequest.onupgradeneeded = function(event) { 
 
     // Objectstore does not exist. Nothing to load 
 
     event.target.transaction.abort(); 
 
     reject(Error('Not found')); 
 
     }; 
 

 
     dbRequest.onsuccess = function(event) { 
 
     var database  = event.target.result; 
 
     var transaction = database.transaction([storeName]); 
 
     var objectStore = transaction.objectStore(storeName); 
 
     var objectRequest = objectStore.get(id); 
 

 
     objectRequest.onerror = function(event) { 
 
      reject(Error('Error text')); 
 
     }; 
 

 
     objectRequest.onsuccess = function(event) { 
 
      if (objectRequest.result) resolve(objectRequest.result); 
 
      else reject(Error('object not found')); 
 
     }; 
 
     }; 
 
    } 
 
); 
 
}

Асинхронное сохранение в IndexedDB:

function saveToIndexedDB(storeName, object){ 
 
    return new Promise(
 
    function(resolve, reject) { 
 
     if (object.id === undefined) reject(Error('object has no id.')); 
 
     var dbRequest = indexedDB.open(storeName); 
 

 
     dbRequest.onerror = function(event) { 
 
     reject(Error("IndexedDB database error")); 
 
     }; 
 

 
     dbRequest.onupgradeneeded = function(event) { 
 
     var database = event.target.result; 
 
     var objectStore = database.createObjectStore(storeName, {keyPath: "id"}); 
 
     }; 
 

 
     dbRequest.onsuccess = function(event) { 
 
     var database  = event.target.result; 
 
     var transaction = database.transaction([storeName], 'readwrite'); 
 
     var objectStore = transaction.objectStore(storeName); 
 
     var objectRequest = objectStore.put(object); // Overwrite if exists 
 

 
     objectRequest.onerror = function(event) { 
 
      reject(Error('Error text')); 
 
     }; 
 

 
     objectRequest.onsuccess = function(event) { 
 
      resolve('Data saved OK'); 
 
     }; 
 
     }; 
 
    } 
 
); 
 
}

Пример кода использования

var data = {'id' : 1, 'name' : 'bla'}; 
 

 
saveToIndexedDB('objectstoreName', data).then(function (response) { 
 
    alert('data saved'); 
 
}).catch(function (error) { 
 
    alert(error.message); 
 
}); 
 

 
// Load some data 
 
var id = 1; 
 
loadFromIndexedDB('objectstoreName', id).then(function (reponse) { 
 
    data = reponse; 
 
    alert('data loaded OK'); 
 
}).catch(function (error) { 
 
    alert(error.message); 
 
});

+0

Спасибо за ответ. Я планировал в будущем использовать чистые обещания или rxjs. С Promise более удобные ошибки catch. Но я хочу сделать код без ошибок. Кроме того, в примере, который вы открываете каждый раз при новом подключении indxedDBbut, но я использую только один. Я думаю, что мы должны использовать что-то вроде шаблонов параллелизма: продюсер и потребитель – Greg

2

Я использовал idb - простая библиотека, которая обертывает IndexedDB с обещаниями. Они делают асинхронные действия DB много проще в использовании.

Если вы ориентируетесь Chrome (или с помощью transpiler, которая их поддерживает), вы можете использовать async и await, чтобы упростить код:

async function saveData(dataArray) { 
    const db = await idb.open('YourDB', currentVersion, upgradeFunction); 
    const tran = await db.transaction('StoreName', 'readwrite'); 
    const store = tran.objectStore('StoreName'); 

    // This will add the items sequentially 
    for(let item of dataArray) { 
     await store.add({data:item}); 
    } 
} 
+0

Спасибо за ваш ответ. IDB - интересная библиотека, но я думаю, что с IndexedDB я могу работать без ненужных оберток. Также проблема этой библиотеки, что она не поймает ошибку при блокировке IndexedDB. Да, моя цель - хром, но я не хочу использовать ее, мой код должен работать и в других браузерах, а также ждать/асинхронно в бета-версии и работать медленно. – Greg

+0

@Greg - async/await являются частью предстоящей спецификации, они не медленнее обещаний, поскольку они в основном просто выполняют эту функциональность. С помощью TypeScript вы можете использовать их, и они перейдут на что-то, что может запустить IE. Я думаю, вы тоже можете с Бабелем, хотя я сам этого не делал. Я не уверен, что вы имеете в виду, что это не ловут ошибки - это не то, что он должен делать, все, что он делает, это обертывание функций обратного вызова с обещаниями. Вы обрабатываете ошибку в своем собственном коде с результатом обещания или заверяете ожидание в регулярной попытке поймать. – Keith

+0

Возможно, вы правы в ожидании/асинхронном режиме, но обычно в новых функциях не оптимизируется. Например, родные обещания работали хуже, чем Polifills. Событие «заблокировано» создается при открытии одного соединения, и мы пытаемся сделать больше. И я думаю, что это событие срабатывает при конфликте двух параллельных транзакций. И вопрос, как избежать этой ошибки. – Greg

Смежные вопросы