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の単純なオブジェクトストアにデータをロードして保存する2つの関数の例を次に示します。

の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')); 
 
     }; 
 
     }; 
 
    } 
 
); 
 
}

非同期:

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

感謝を。 私は将来、きれいなPromise、つまりrxjsを使う予定でした。プロミスでより快適なキャッチエラー。しかし、私はエラーを発生させずにコードを作成したい。 さらに、この例では、新しいindxedDBbut接続を毎回開きますが、私は1つだけを使用します。 私はコンカレントパターンのようなものを使うべきだと思います:プロデューサーとコンシューマー – Greg

2

IndexedDBを約束してくれる単純なライブラリidbを使っています。これにより、非同期DBアクションが多く、が使いやすくなります。

あなたは、あなたのコードを簡素化するためにasyncawaitを使用することができますChromeをターゲットにしている(またはそれらをサポートしていtranspilerを使用している)場合は、次の答えを

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を実行できるようになります。私はあなた自身もそれをやったことはありませんが、あなたもバベルと一緒にできると思います。私はエラーをキャッチしないことについてあなたが何を意味するのか分かりません。それは、それがするべきことではないから、約束でコールバック関数をラップするだけです。約束の結果であなた自身のコードでエラーを処理するか、定期的なtry catchで待ち時間をラップします。 – Keith

+0

おそらくあなたは待機/非同期については正しいですが、通常は新しい機能の初めに最適化されていません。たとえば、ネイティブプロミスはPolifillsより悪化しました。 イベント「ブロックされました」は、1つの接続が開いているときに作成され、さらに処理を試みます。 そして、このイベントは、2つの同時トランザクションが競合するときに発生すると考えられます。 質問このエラーを回避するにはどうすればよいですか。 – Greg

関連する問題