プログラム学習室 http://studyhallweb.com/

Dart言語: Indexed DB

デモンストレーション (Demonstration)


Key: Value:


-------------- indexedDB recoard --------------

    サンプルコード (Sample Code)

    HTML

    <output id="pgmComment"></output><br/>  <!-- indexedDB をサポートしてない場合、コメントを表示 -->
    Key:<input type="text" id="newKey">
    Value:<input type="text" id="newValue">
    <input type="submit" id="addRecord" value="Save"><br/>
    <input type="submit" id="btn-search" value="Search"><br/>
    <br/>
    -------------- indexedDB recoard --------------<br/>
    <ul id="db-items"></ul>
    					

    Dart

    import 'dart:html';
    import 'dart:indexed_db';
    import 'dart:async';  // Future
    
    const DEBUG = 0;
    
    /**
     * IndexedDB
     * 参考:https://www.dartlang.org/docs/tutorials/indexeddb/
     * https://github.com/dart-lang/dart-samples/blob/master/html5/web/indexeddb/todo/todo.dart
     */
    class indexDB {
      static final String _DB_NAME = 'db028';
      static final String _DB_STORE = 'db028s';
      static final String _DB_INDEX = 'db028index';
    
      Database _db;    // indexed_db
      int _version = 2;
      Element _dbItems;
    
      indexDB() {
        // indexedDBをサポートしているかチェック
        if (IdbFactory.supported) {
          _dbItems = querySelector('#db-items');
          _open();
        }
        else{
          Element comment = querySelector('#pgmComment');
          comment.text = 'このブラウザでは indexedDB はサポートされていません';
        }
      }
      // indexedDBのオープン
      Future _open() {
        return window.indexedDB.open(_DB_NAME, version: _version, onUpgradeNeeded: _initializeDatabase)
          .then(_dbOpend);
      }
      // 新規のindexedDBの場合、初期化
      void _initializeDatabase(VersionChangeEvent e) {
        Database iniDB = (e.target as OpenDBRequest).result;
        if (!iniDB.objectStoreNames.contains(_DB_STORE)) {
          iniDB.createObjectStore(_DB_STORE, keyPath: 'keyWord');
        }
      }
      void _dbOpend(Database db) {
        // indexedDBがオープンされたときに実行
        _db = db;
        _getAllItemsFromDB();
        if (DEBUG > 0) window.console.log('db opened');
        querySelector('input#addRecord').onClick.listen((e) => _onAddRecord());
        querySelector('input#btn-search').onClick.listen((e) => _onSearchRecord());
      }
      /**
       * keyWord でレコード検索
       */
      void _onSearchRecord() {
        if (DEBUG > 0) window.console.log('_onSearchRecord');
        InputElement inpKey = querySelector('#newKey');
        InputElement inpValue = querySelector('#newValue');
        inpValue.value = "";
        var key = inpKey.value.trim();
        if (key.length > 0) {
          var trans = _db.transaction(_DB_STORE, 'readonly');
          var store = trans.objectStore(_DB_STORE);
          var val = store.getObject(inpKey.value);
          val.then((val) => _getValue(val));  // future のため
        }
      }
      void _getValue(Map val) {
        if (DEBUG > 0) window.console.log(val.toString());
        InputElement inpValue = querySelector('#newValue');
    
        inpValue.value = val['value'].toString();
      }
      /**
       * レコード追加
       */
      void _onAddRecord() {
        InputElement inpKey = querySelector('#newKey');
        InputElement inpValue = querySelector('#newValue');
        var key = inpKey.value.trim();
        if (key.length > 0) {
          var value = inpValue.value.trim();
          _addRecord(key, value);
        }
        inpKey.value = '';
        inpValue.value = '';
      }
      Future _addRecord(String key, String text) {
        if(DEBUG > 0) {
          window.console
            ..log('_addRecord()')
            ..log('key:' + key + ' Value:' + text);
        }
        var trans = _db.transaction(_DB_STORE, 'readwrite');
        var store = trans.objectStore(_DB_STORE);
        store.put({
          'value': text,
          'keyWord': key})
          .catchError((e) => _onError);
        // 複数のtransactionが実行されたとき、全てのtransactionが終了しないと
        // transaction.complated.then()は実行されない
        return trans.completed.then((_) => _getAllItemsFromDB());
      }
      /**
       * keyWord でレコード削除
       */
      void _deleteRecord(String id) {
        if (DEBUG > 0) {
          window.console
            ..log('_deleteRecord()')
            ..log('delete key = $id');
        }
        var trans = _db.transaction(_DB_STORE, 'readwrite');
        var store =  trans.objectStore(_DB_STORE);
        var request = store.delete(id);
        request.then((e) => _getAllItemsFromDB(), onError: _onError);
      }
      /**
       * indexedDBの内容を _dbItmes に表示する
       */
      void _getAllItemsFromDB() {
        if (DEBUG > 0) window.console.log('_getAllItemsFromDB');
    
        _dbItems.nodes.clear();    // 表示を全消去
        var trans = _db.transaction(_DB_STORE, 'readwrite');
        var store = trans.objectStore(_DB_STORE);
    
        // Get everything in the store.
        var request = store.openCursor(autoAdvance:true).listen((cursor) {
          if (DEBUG > 0) window.console.log(cursor.value.toString());
          _setItem(cursor.value);
        }, onError: _onError);
      }
      // レコード内容を表示する
      void _setItem(Map dbRecord) {
        var textDisplay = new Element.tag('span');
        textDisplay.text = 'key:' + dbRecord['keyWord'] + ', value:' + dbRecord['value'];
    
        // 削除リンクの追加
        var deleteControl = new Element.tag('a');
        deleteControl.text = ' [Delete]';
        deleteControl.onClick.listen((e) => _deleteRecord(dbRecord['keyWord']));
    
        var item = new Element.tag('li');
        item.nodes.add(textDisplay);
        item.nodes.add(deleteControl);
        _dbItems.nodes.add(item);
      }
    
      void _onError(e) {
        window.alert('Oh no! Something went wrong. See the console for details.');
        window.console.log('An error occurred: {$e}');
      }
    }
    main() {
      new indexDB();
    }
    					

    説明

    前回動かなかった理由

    前回試したとき(2014年6月)は動きませんでした。
    そのときは Dart の STABLE(安定版)ではなく、開発版でした。
    そのため、動かなかったのだと思います。

    Dart を再インストールして気が付いたのですが、自分の Dart は開発版だったのです。
    初めてインストールしたのは、それほど前ではなかったと思うのですが、twitter などでいわれていたバージョンより自分のバージョンが高いので、おかしいなとは思っていました。

    上にに書いたものは、もっとも簡単なサンプルと思われる GitHub の dart-samples をまねて書いたものです。
    dart-samples のソースはこちら。
    https://github.com/dart-lang/dart-samples/tree/master/html5/web/indexeddb/todo

    Database と Transaction と ObjectStore

    Databaseオブジェクトに対して直接処理が出来るわけではなく、Transaction とそれに紐づいた ObjectStore が必要です。
    Transaction は、"readonly"、"readwrite"、"versionchangetransaction" の3つのモードがあります。
    Transaction に対して、ObjectStore を定義して、その ObjectSotore でレコードの追加・削除などを行います。

    get() ではなく getObject()

    key を指定してレコードを取得するメソッドは、JavaScript では get() のようですが、 Dart は getObject() になります。