IndexedDB:クックしようとしています

IndexedDB-大量の構造化データをクライアントに保存するための標準である-WebSocketと同様に期待されていました(まあ、少し少ないかもしれません)。 FireFox 4のリリースに照らして、私はそれを使用する方法を見つけ出し、インターネット上を歩いているアドレス帳で例以上のものを書き込もうとする時間と強さを見つけました(情報を検索する過程で、それが唯一のものであるという印象を持っていました例)。



いくつかの紹介的な言葉



IndexedDBは、索引付けの可能性がある大量の構造化データを格納するために使用されます。 このようなツールキットの必要性は長らく待ち望まれていたため、HTML5仕様に登場しました。 簡単な背景はここで見つけることができます



テキストには、感情の解放に必要な叙情的な余談があります。 記事にウィキスタイルへのリンクを振りかけたくありません。すべてのソースが最後に積み重ねられています。



何を訓練しますか



偶然、最近チャットルームを作成しました。 そこで、次の要件を備えたチャットルームを構築します。



行こう



最初のステップは、ブラウザーでIndexedDBのサポートがあるかどうかを確認することです。 これは次のように行われます。

if ("webkitIndexedDB" in window){ var idb=window.webkitIndexedDB; } else if ("mozIndexedDB" in window) { var idb=window.mozIndexedDB; } else { // ,         -    };
      
      







:

, . , , ( ), , , -, .









次に、タイプIDBRequestのオブジェクトを作成する必要があります。これにより、データベースオブジェクトへの非同期アクセスが提供されます。 ドラフト仕様のIndexedDBへの同期アクセスは存在しますが、まだ実装されていません。

 var idbRequest=idb.open(dbName,dbDescription); //dbName –   , dbDescription –   () //     idbRequest.onsuccess=function (e) {…}; idbRequest.onerror=function (e) {…};
      
      







Onerrorハンドラー:

仕様を信じるなら、引数として、IDBErrorEvent型のオブジェクトが飛び、コードとメッセージという2つのプロパティを持っている必要があります。 実際には、プロパティにIDBRequestオブジェクトがあり、そこからエラーコードと、Webkitの場合はメッセージ自体を取得できる単純なイベントが到着します。 最終ハンドラーの構造は次のとおりです。

 function idbRequestError(err){ idbRequest=err.target; //  idbRequest.errorCode // webkit,   idbRequest.webkitErrorMessage; }
      
      







このエラーの呼び出しは非常に簡単です:



接続が成功したら、続行して、ユーザーが正しいデータベースを持っているかどうか、および正しいバージョンを持っているかどうかを確認できます。 成功したハンドラー構造:

 function idbRequestSuccess(e){ var db=e.target.result; if (db.version===''){ //   }else if (db.version!='3.14'){ //     } else { //  }; }
      
      







データベースがない場合、またはデータベースのバージョンが正しくない場合は、データベースを作成または変更する必要があります。 これを行うには、setVersionメソッドが必要です。 ここでは、コードの記述から注意をそらし、IndexedDBのトランザクションメカニズムについて説明する必要があります。



IndexedDBのトランザクション



W3Cドラフトでは、READ_ONLY、READ_WRITE、SNAPSHOT_READ、VERSION_CHANGEDの4種類のトランザクションを定義しています。





, READ_ONLY SNAPSHOT_READ, , , .








READ_ONLY-名前が示すように、読み取りに役立ちます。 他のタイプのトランザクションをブロックします。

READ_WRITE-データを変更し、選択したオブジェクトで競合するすべてのトランザクションの完了を待機し、他のすべてのトランザクションをブロックして実行します。

VERSION_CHANGE-他のすべてのトランザクションの完了を待機し、すべてのユーザーのデータオブジェクトへのアクセスをブロックして実行されるトランザクション。 このトランザクションでのみ、データオブジェクトを作成、削除、または変更できます。





. W3C READ_WRITE=0, READ_ONLY=1, SNAPSHOT_READ=2, VERSION_CHANGE=3. “webkitIDBTransaction.READ_ONLY” , , . , VERSION_CHANGE 2, . , FireFox READ_ONLY=0, READ_WRITE=1 .









データオブジェクトの作成



既に述べたように、トランザクションVERSION_CHANGEからのみデータオブジェクトを操作できます。 バージョン変更が成功したハンドラーから接続できます。

 var setVersion=db.setVersion('3.14'); setVersion.onsuccess=function (e) { var db=e.target.transaction.db; //    };
      
      







データオブジェクトでできること:

作成-createObjectStore()

削除-deleteObjectStore()

トランザクションを割り当てる-トランザクション()



削除に対処します



引数として、deleteメソッドは削除するデータオブジェクトの名前を取ります。 メソッドは非同期で実行され、理論的には、onsuccessハンドラーをアタッチできるIDBRequest型のオブジェクトを返す必要があります。 しかし、WebkitもMozillaも、何かを返す必要があるとは考えていません。 ただし、このメソッドは非同期に機能し、競合するメソッドへのアクセスをブロックします。 建設の使用のため

 for (var i=0; i<db.objectStoreNames.length; i++){ db.deleteObjectStore(db.objectStoreNames.length[i]); };
      
      





予測不可能な結果につながります。 残すもの、ないもの。 通常の方法が機能しないことを確認します。 松葉杖の構造は、原則として理解できますが、私はそれを気にしないことに決めました。 概して、データベースの構造が変更された場合にのみオブジェクトを削除する必要があります。



オブジェクトを作成する



この例では、アドレス帳を使用して、データベースオブジェクトを1つだけ作成しました。 しかし、2つのオブジェクトを作成することにしたとき、FireFoxはトピックNON_TRANSIENT_ERRで私を覆い隠し始めました。



当初、設計は次のとおりで、Chromeで正常に機能しました。

 var setVersion=db.setVersion(dbVersion); setVersion.onsuccess=idbCreateStore; function idbCreateStore(e){ //   ,   VERSION_CHANGE  var db=e.target.transaction.db; if (!db.objectStoreNames.contains('chat')){ //      soChat=db.createObjectStore('chat', 'id'); soChat.createIndex('itime','time'); }; if (!db.objectStoreNames.contains('iam')){ //     soIam=db.createObjectStore('iam'); }; }
      
      







数時間の実験の後、Chromeでも機能するFireLisのハックが作成されました。

 var setVersion=db.setVersion('4'); setVersion.onsuccess=idbCreateStore; function idbCreateStore(e){ //   ,   VERSION_CHANGE  var db=e.target.transaction.db; if (!db.objectStoreNames.contains('chat')){ //      co=db.createObjectStore('chat','id'); setVersion=db.setVersion('42') setVersion.onsuccess=idbCreateStore; return; }; if (!db.objectStoreNames.contains('iam')){ //     co=db.createObjectStore('iam'); }; }
      
      







お気づきかもしれませんが、オブジェクトを作成する前に、データベースにそのようなオブジェクトが既に存在するかどうかを確認するためのチェックが進行中です。 これは、オブジェクトの削除を混乱させないために行われます。 データベースにすでに存在するオブジェクトを作成しようとすると、エラーが発生します。



オブジェクトを作成するためのオプションの引数:キー名と自動非侵害フラグ(ブラウザでは無視されます)。



また、インデックスの作成はコードから消えました。OgneLisは、バージョン変更トランザクションでのインデックスの作成に苦痛を感じました。



この時点で、データベースが形成されます。 続行できるようです。 しかし、これはそうではありません。 すべての呼び出しは非同期で行われるため、すべてのオブジェクトが作成されたことを明確に述べることはできません。 繰り返しますが、仕様によると、createObjectStore()メソッドによって返されるIDBObjectStoreオブジェクトには、IDBRequestプロパティが含まれている必要があります。これは、onsuccessハンドラーでハングさせることができます。 しかし、オブジェクトには同様のプロパティはありません。 したがって、メインの作業サイクルを開始する前に、データベースオブジェクトの作成が完了するまで待つ必要があります。これは、次のトリッキーではないコードによって実行されます。

 var idbObjectsWait=true; while (idbObjectsWait){ idbObjectsWait=!(db.objectStoreNames.contains('chat') && db.objectStoreNames.contains('iam')); };
      
      





最後に、データベースが作成されたので、書き留めたものに書き込み、読み取りを開始できます。



記録



データを書き込む方法は2つあります(書き込みトランザクションからのみ)。追加と書き込みです。 違いは次のとおりです。追加するオブジェクトに既に存在するキーを追加すると、値は書き込まれません。 put-データを置き換えます。 操作は再び非同期です。

 var t=idb.transaction(['iam'], idbConst.WRITE); var s=t.objectStore('iam'); s.put({'name':$('#name').val()},1);
      
      







読書



       .          IDBKeyRange,      ,      . ..       :  .  ,   : var t=idb.transaction(['chat'],idbConst.READ); var s=t.objectStore('chat'); var r=s.openCursor(); r.onsuccess=function (e) { var idbEntry=e.target.result; if (idbEntry){ //,       idbEntry.continue(); } else { //  }; };
      
      







ポインターの初期位置を制御することはできませんが、continueメソッドにパラメーターを渡すことで読み取り方向を操作できます。



おわりに



実際、あまり楽観的ではありませんが、これで終わりです。 IndexedDBの実装は非常に未加工です。サボテンは非常に傷つきやすく、テキーラは出てきません。 アプリケーションの範囲は非常に限られており、IndexedDBのコードを書くことは、ブラウザの数が少ないことを含め、明らかにそれ自体にお金を払っていません。



トピックの見どころ



マイクウエスト

developer.mozilla.org/en/IndexedDB-Mozillaの開発ドキュメント。

www.w3.org/TR/IndexedDB-W3C仕様。

www.netroxsc.ru/pub/chateg-Chrome 11および12でテストされたChromeの例、およびプロジェクトソース



UPD 2014-04-09 。 更新されたIndexDBの記事: IndexedDBの準備



All Articles