Ikkyu's Tech Blog

技術系に関するブログです。

IndexedDBを使ってみる

今作っているアプリの保存機能をどうしようか考えていて、 前から気になっていたIndexedDBを使うことにしました。 その際、調べたので基本的な使い方をまとめます!

用語や概要の説明はしません。簡単な使い方のみ説明します。 用語や概要はIndexedDB API - Web API | MDNを見てください。

扱うデータは以下の通りです。

  • DB名: myDatabase
  • objectStore名: myObjectStore
id firstName lastName age
1 一郎 山田 30
2 次郎 山田 27
3 一郎 田中 27

DB, objectStoreを作成

// 指定したDBへ接続(ない場合は作成)
const request = indexedDB.open('myDatabase')

// 作成 or バージョンを更新した場合
request.onupgradeneeded = event => {
  // dbを取得
  const db = event.target.result
  // objectStoreを作成
  const objectStore = db.createObjectStore("myObjectStore", { keyPath: "id" }) // keyPathは、一意となるプロパティ名を指定(Primary Keyみたいな感じ)
  // index作成(lastName) ... lastNameは重複を許可してるので、unique: falseを指定
  objectStore.createIndex("lastName", "lastName", { unique: false })
  // index作成(age) .... ageも重複を許可してるので、unique: falseを指定
  objectStore.createIndex("age", "age", { unique: false })
}

// 成功の場合
request.onsuccess = event => {
  // 接続成功時の処理
}

// 失敗の場合
request.onerror = event => {
  // 接続失敗時の処理
}

データを追加

const request = indexedDB.open('myDatabase')

request.onsuccess = event => {
  // dbを取得
  const db = event.target.result

  // transactionを取得
  const transaction = db.transaction(["myObjectStore"], "readwrite") // 追加するので"readwrite"を指定

  transaction.oncomplete = e => { console.log("success!!") }

  transaction.onerror = e => { console.error("error: ", e) }

  // objectStoreを取得
  const objectStore = transaction.objectStore("myObjectStore")
  objectStore.add({ id: 1, firstName: "一郎", lastName: "山田", age: 30 })
  objectStore.add({ id: 2, firstName: "次郎", lastName: "山田", age: 27 })
  objectStore.add({ id: 3, firstName: "一郎", lastName: "田中", age: 27 })
}

データを取得

keyPathを使用してデータを取得

const request = indexedDB.open('myDatabase')

request.onsuccess = event => {
  // dbを取得
  const db = event.target.result

  // transactionを取得
  const transaction = db.transaction(["myObjectStore"])

  // objectStoreを取得
  const objectStore = transaction. objectStore("myObjectStore")

  // requestを取得
  const req = objectStore.get(1)

  req.onsuccess = e => { console.log("success: ", e.target.result) } // { id: 1, firstName: "一郎", lastName: "山田", age: 30 } }
 
  req.onerror = e => { console.error("error: ", e) }
}

cursorを使用してデータを取得

keyPath知らない場合、objectStoreを昇順(keyPath)に検索
(indexがあるので、あまり使わない方法かも...)

const request = indexedDB.open('myDatabase')

request.onsuccess = event => {
  // dbを取得
  const db = event.target.result

  // transactionを取得
  const transaction = db.transaction(["myObjectStore"])

  // objectStoreを取得
  const objectStore = transaction. objectStore("myObjectStore")

  // requestを取得
  const req = objectStore.openCursor()

  req.onsuccess = e => {
    // cursorを取得
    const cursor = e.target.result
    if (cursor) {
      console.log("cursor: ", cursor, " value: ", cursor.value)
      cursor.continue();  // cursorを移動させてる
    }
  }
 
  req.onerror = e => { console.error("error: ", e) }
}

indexを使用してデータを取得

const request = indexedDB.open('myDatabase')

request.onsuccess = event => {
  // dbを取得
  const db = event.target.result

  // transactionを取得
  const transaction = db.transaction(["myObjectStore"])

  // objectStoreを取得
  const objectStore = transaction. objectStore("myObjectStore")

  // indexを取得
  const index = objectStore.index("age");

  // 一番最初のvalueを取得
  index.get("一郎").onsuccess = e => {
    console.log("success: ", e.target.result) // { id: 1, firstName: "一郎", lastName: "山田", age: 30 }
  }

  // indexの全てのvalueを取得
  index.openCursor().onsuccess = e => {
    const cursor = e.target.result
    if (cursor) {
      console.log("cursor: ", cursor, " value: ", cursor.value)
      cursor.continue();  // cursorを移動させてる      
    }
  }

  // indexの全てのkeyPathを取得
  index.openKeyCursor().onsuccess = e => {
    const cursor = e.target.result
    if (cursor) {
      console.log("cursor: ", cursor, " keyPath: ", cursor.value)
      cursor.continue();  // cursorを移動させてる      
    }
  }
}

データを更新

const request = indexedDB.open('myDatabase')

request.onsuccess = event => {
  // dbを取得
  const db = event.target.result

  // transactionを取得
  const transaction = db.transaction(["myObjectStore"], "readwrite") // 追加するので"readwrite"を指定

  // objectStoreを取得
  const objectStore = transaction. objectStore("myObjectStore")

  // requestを取得
  const req = objectStore.get(1)

  req.onsuccess = e => {
    const data = e.target.result
    // データを変更
    data.age = 33
    // 変更リクエストを取得
    const updateRequest = objectStore.put(data)

    updateRequest.onsuccess = e => { console.log("success: ", e) }
 
    updateRequest.onerror = e => { console.error("error: ", e) } 
  }
 
  req.onerror = e => { console.error("error: ", e) }
}

データを削除

const request = indexedDB.open('myDatabase')

request.onsuccess = event => {
  // dbを取得
  const db = event.target.result

  // transactionを取得
  const transaction = db.transaction(["myObjectStore"], "readwrite") // 追加するので"readwrite"を指定

  // objectStoreを取得
  const objectStore = transaction. objectStore("myObjectStore")

  // requestを取得
  const req = objectStore.delete(1)

  req.onsuccess = e => { console.log("success: ", e) } // 削除完了
 
  req.onerror = e => { console.error("error: ", e) }
}

以上です。

indexedDBのラッパークラス作って、Promise返すメソッド作れば使いやすくなるかもって思ってます。有名なライブラリがあるけど、簡単なライブラリでも作ってみようかな....