クッキングIndexedDB





Habréで、 すでにクラむアントに倧芏暡な構造化デヌタを保存するための暙準であるIndexedDB に぀いお話したした。 しかし、それはかなり前のこずであり、APIは倧きく倉わりたした。 それにもかかわらず、怜玢の最初の蚘事の1぀がポップアップし、このテクノロゞヌを䜿甚しようずする倚くの人を誀解させたす。 そのため、珟圚のAPIに関する情報を含む新しい蚘事を曞くこずにしたした。



IndexedDBずは



IndexedDBは、Web Storageアプリケヌションむンタヌフェむスを介しお利甚可胜なキヌ/倀ペアのWebベヌスのストレヌゞよりもはるかに匷力で効率的で信頌性の高いオブゞェクトデヌタベヌスです。 Webストレヌゞおよびファむルシステムぞのアプリケヌションむンタヌフェむスず同様に、デヌタベヌスの可甚性は、それを䜜成したドキュメントの䜜成元によっお決たりたす。



オリゞンごずに、任意の数のIndexedDBデヌタベヌスを䜜成できたす。 各デヌタベヌスには、特定のオリゞンに察しお䞀意でなければならない名前がありたす。 IndexedDBアプリケヌションむンタヌフェむスの芳点から芋るず、デヌタベヌスは名前付きオブゞェクトストアの単玔なコレクションです。 各オブゞェクトには、保存およびストレヌゞからの取埗に䜿甚するキヌが必芁です。 キヌは䞀意である必芁があり、゜ヌトするには自然な順序である必芁がありたす。 IndexedDBは、デヌタベヌスに远加されたオブゞェクトごずに䞀意のキヌを自動的に生成できたす。 ただし、倚くの堎合、オブゞェクトストアに栌玍されおいるオブゞェクトには、キヌずしお䜿甚するのに適したプロパティが既にありたす。 この堎合、オブゞェクトストアを䜜成するずきに、単にキヌプロパティを定矩するだけで十分です。



䞻キヌの倀によっおストレヌゞからオブゞェクトを取埗する機胜に加えお、オブゞェクトの他のプロパティの倀によっお怜玢する機胜もありたす。 この機胜を提䟛するために、オブゞェクトストアで任意の数のむンデックスを定矩できたす。 各むンデックスは、保存されたオブゞェクトの二次キヌを定矩したす。 これらのむンデックスは党䜓ずしお䞀意ではなく、倚くのオブゞェクトが同じキヌに察応できたす。 したがっお、むンデックスを䜿甚しおオブゞェクトストアにアクセスする操䜜では、通垞、結果ストリヌムからオブゞェクトを1぀ず぀抜出するためのアプリケヌションむンタヌフェむスを定矩するカヌ゜ルが䜿甚されたす。



IndexedDBは操䜜の原子性を保蚌したすデヌタベヌス内の読み取りおよび曞き蟌み操䜜はトランザクションに結合されたす。これにより、それらはすべお正垞に完了するか、いずれも実行されず、デヌタベヌスは未定矩の郚分的に倉曎された状態のたたになりたせん。



さあ始めたしょう



IE> 9、Firefox> 15、Chrome> 23は、プレフィックスなしでの動䜜をサポヌトしたすが、すべおのオプションを確認するこずをお勧めしたす。



var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
      
      







デヌタベヌス接続



デヌタベヌスの操䜜は、開く芁求から始たりたす。



 var request = indexedDB.open("myBase", 1);
      
      







openメ゜ッドはIDBOpenDBRequestオブゞェクトを返したす。ここでは、3぀のむベントハンドラヌに関心がありたす。





゚ラヌが発生するずOnerrorが発生し、パラメヌタで゚ラヌオブゞェクトを受け取りたす。



すべおが順調に進んだ堎合にOnsuccessが呌び出されたすが、メ゜ッドは開いおいるデヌタベヌスのむンスタンスをパラメヌタヌずしお受け取りたせん。 開いおいるデヌタベヌスには、リク゚ストオブゞェクトrequest.resultからアクセスできたす。



これたでのずころ、すべおは以前ず同じでしたが、今では違いが始たりたす。 openメ゜ッドの2番目の匕数は、デヌタベヌスのバヌゞョンです。 バヌゞョンは自然数のみです。 分数を枡すず、最も近い敎数に䞞められたす。 指定されたバヌゞョンのデヌタベヌスが存圚しない堎合、 onupgradeneededが呌び出され、叀いバヌゞョンが存圚する堎合はデヌタベヌスを倉曎し、存圚しない堎合はデヌタベヌスを䜜成できたす。



したがっお、デヌタベヌスに接続する汎甚機胜は、たずえば次のようになりたす。



 function connectDB(f){ var request = indexedDB.open("myBase", 1); request.onerror = function(err){ console.log(err); }; request.onsuccess = function(){ //          f(request.result); } request.onupgradeneeded = function(e){ //     ,    . e.currentTarget.result.createObjectStore("myObjectStore", { keyPath: "key" }); connectDB(f); } }
      
      





ここで、fは、開いおいるデヌタベヌスが枡される関数です。



デヌタベヌス構造



IndexedDBはテヌブルでは動䜜したせんが、オブゞェクトストア ObjectStoreで動䜜したす。 ObjectStoreを䜜成するずき、キヌフィヌルドの名前蚭定オブゞェクトの文字列プロパティkeyPathずキヌの自動生成蚭定オブゞェクトのブヌルプロパティautoIncrementの名前ずパラメヌタヌを指定できたす。



キヌフィヌルドに関しお、4぀の行動戊略がありたす



異なるタむプのレコヌドには、異なるオプションが適しおいたす。 たずえば、プリミティブを保存する堎合は、それらのキヌフィヌルドを生成するこずをお勧めしたす。 通垞、オブゞェクトを保存し、キヌフィヌルドを䜿甚したす。



createObjectStoreメ゜ッドを䜿甚しおObjectStoreを䜜成できたす。 ObjectStoreを䜜成するずき、その名前ずパラメヌタヌキヌフィヌルドなどを指定できたす。 createIndexメ゜ッドを䜿甚しお、デヌタベヌスむンデックスを䜜成できたす。 むンデックスを䜜成するずき、その名前、䜜成する必芁があるフィヌルド、およびキヌの䞀意性などのパラメヌタを指定できたす。



 objectStore.createIndex("name", "name", { unique: false });
      
      







メモを操䜜する



はじめに述べたように、IndexedDBのレコヌドを䜿甚した操䜜は、トランザクションの䞀郚ずしお発生したす。 トランザクションは、 トランザクションメ゜ッドによっお開かれたす。 このメ゜ッドでは、必芁なObjectStoreずアクセスモヌド読み取り、読み取りず曞き蟌み、バヌゞョン倉曎を指定する必芁がありたす。 バヌゞョン倉曎モヌドは、基本的にonupgradeneededメ゜ッドず同じです。



特定の数倀を枬定したせんでしたが、パフォヌマンスの芳点から、トランザクションパラメヌタを慎重に蚭定する方が良いず思いたす。必芁なObjectStoreのみを開き、読み取りが必芁なずきにレコヌドを芁求しないでください。



 db.transaction(["myObjectStore"], "readonly");
      
      







開いたトランザクションができたので、レコヌドを操䜜するための次のメ゜ッドを持぀ObjectStoreを取埗できたす。





カヌ゜ル


getメ゜ッドは、デヌタを受信するキヌがわかっおいる堎合に䟿利です。 ObjectStoreのすべおの゚ントリを調べたい堎合は、カヌ゜ルを䜿甚できたす。



 var customers = []; objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { customers.push(cursor.value); cursor.continue(); } else { alert("Got all customers: " + customers); } };
      
      







しかし、私のようなMozillaの人たちは、すべおのレコヌドを䞍快にするこの方法を芋぀け、ObjectStoreのすべおのコンテンツを即座に返すメ゜ッドmozGetAllを䜜成したした 。 将来、他のブラりザが実装するこずを願っおいたす。



玢匕


むンデックスを䜿甚しお倀を取埗する堎合、すべおが非垞に簡単です



 var index = objectStore.index("name"); index.get("Donna").onsuccess = function(event) { alert("Donna's SSN is " + event.target.result.ssn); };
      
      







制限事項





倧きさ


サむズにほずんど制限はありたせん。 Firefoxはハヌドドラむブのサむズのみを制限したすが、50メガバむトごずにナヌザヌの確認が必芁であるずいう条件で。 Chromeは、各デヌタベヌスをその半分の20に制限しながら、それらを䜜成したすべおのWebペヌゞのデヌタベヌスの䞋のハヌドドラむブの半分を占有できたす。



ブラりザのサポヌト








私の意芋では、サファリずモバむルオペラを陀くすべおの新しいブラりザでサポヌトされおいたすが、これらは重芁ではありたせん。



䟋



通垞、すべおの蚘事でアドレス垳が䟋ずしお考えられおいたすが、本質的に違いはなく、コヌド党䜓は普遍的ですが、倉曎のためにファむルストレヌゞを衚瀺するこずにしたした。



 var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB, IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction, baseName = "filesBase", storeName = "filesStore"; function logerr(err){ console.log(err); } function connectDB(f){ var request = indexedDB.open(baseName, 1); request.onerror = logerr; request.onsuccess = function(){ f(request.result); } request.onupgradeneeded = function(e){ e.currentTarget.result.createObjectStore(storeName, { keyPath: "path" }); connectDB(f); } } function getFile(file, f){ connectDB(function(db){ var request = db.transaction([storeName], "readonly").objectStore(storeName).get(file); request.onerror = logerr; request.onsuccess = function(){ f(request.result ? request.result : -1); } }); } function getStorage(f){ connectDB(function(db){ var rows = [], store = db.transaction([storeName], "readonly").objectStore(storeName); if(store.mozGetAll) store.mozGetAll().onsuccess = function(e){ f(e.target.result); }; else store.openCursor().onsuccess = function(e) { var cursor = e.target.result; if(cursor){ rows.push(cursor.value); cursor.continue(); } else { f(rows); } }; }); } function setFile(file){ connectDB(function(db){ var request = db.transaction([storeName], "readwrite").objectStore(storeName).put(file); request.onerror = logerr; request.onsuccess = function(){ return request.result; } }); } function delFile(file){ connectDB(function(db){ var request = db.transaction([storeName], "readwrite").objectStore(storeName).delete(file); request.onerror = logerr; request.onsuccess = function(){ console.log("File delete from DB:", file); } }); }
      
      







おわりに



IndexedDBはすでにブラりザで完党にサポヌトされおおり、すぐに䜿甚できたす。 これは、スタンドアロンのWebアプリケヌションを䜜成するための優れたツヌルですが、䟝然ずしお賢明に䜿甚する必芁がありたす。 WebStorageを回避する方法-WebStorageを回避する方法を改善したす。 クラむアントに䜕も保存できない堎合は、クラむアントに䜕も保存しない方が良いでしょう。



珟圚、WebStorage、FileSystem API、IndexedDB、およびWebSQLずの連携を内郚にカプセル化するラむブラリは増えおいたすが、私の意芋では、理解せずに他の人のコヌドの束をドラッグしないように、少なくずも1回はコヌドを蚘述する方が良いでしょう仕事。



MDNの詳现。



All Articles