essay | tech | year-summary | about

返回上级菜单

Indexed DB memo


日期:2024-04-06T00:00:00Z

Because local storage will be overflow when image is bigger than 800kb (when saved in base64 format)
Decided to use indexed db to cache my imgs then to save my money.
Here is how to use indexed db.

open db (onload)

key path and auto increment

key path auto increment description
no no This object store can hold any kind of value, even primitive values like numbers and strings. You must supply a separate key argument whenever you want to add a new value.
no yes This object store can only hold JavaScript objects. The objects must have a property with the same name as the key path.
yes no This object store can hold any kind of value. The key is generated for you automatically, or you can supply a separate key argument if you want to use a specific key.
yes yes This object store can only hold JavaScript objects. Usually a key is generated and the value of the generated key is stored in the object in a property with the same name as the key path. However, if such a property already exists, the value of that property is used as key rather than generating a new key.

ref: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB

const openDB = () => {
    return new Promise((resolve, reject) => {

        const dbVersion = 1
        const request = indexedDB.open("CandyImgs", dbVersion);

        request.onerror = (event) => {
            reject("Error opening database");
        };

        request.onsuccess = (event) => {
            const db = event.target.result;
            resolve(db);
        };

        // when upgrade db version, eg. upgrade db structure etc
        request.onupgradeneeded = (event) => {
            const db = event.target.result;
            const objectStore = db.createObjectStore("Imgs", { keyPath: "imgUrl", { autoIncrement: false } });
            // objectStore.createIndex("name", "name", { unique: false });

            objectStore.transaction.oncomplete = (event) => {
                // check insert db part
            };

        };
    });
};

insert db

const addDataToDB = (db: IDBDatabase, data: { imgUrl: string, imgCacheUrl: string }) => {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction(["Imgs"], "readwrite");
        const objectStore = transaction.objectStore("Imgs");
        const request = objectStore.add(data);
        request.onerror = (event) => {
            reject("Error adding data to database");
        };
        request.onsuccess = (event) => {
            resolve("Data added to database", data?.imgUrl);
        };
    });
}

select db

const getDataFromDB = (db: IDBDatabase) => {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction(["Imgs"], "readonly");
        const objectStore = transaction.objectStore("Imgs");
        const request = objectStore.getAll();
        request.onerror = (event) => {
            reject("Error retrieving data from database");
        };
        request.onsuccess = (event) => {
            const data = event.target.result;
            resolve(data);
        };
    });
};

const getSingleDataFromDB = (db: IDBDatabase, imgUrl: string) => {
    return new Promise<string>((resolve, reject) => {
        if (!imgUrl) return resolve("");
        const transaction = db.transaction(["Imgs"], "readonly");
        const objectStore = transaction.objectStore("Imgs");
        // const index = objectStore.index("imgUrl");
        // const request = index.get(imgUrl);
        const request = objectStore.get(imgUrl);
        request.onerror = (event) => {
            reject("Error retrieving data from database");
        };
        request.onsuccess = (event) => {
            const data = event.target.result;
            // console.log(data);
            resolve(data?.imgCacheUrl);
        };
    });
}

// if you created a index
const getSingleDataFromDB = (db: IDBDatabase, imgUrl: string) => {
    return new Promise<string>((resolve, reject) => {
        if (!imgUrl) return resolve("");
        const transaction = db.transaction(["Imgs"], "readonly");
        const objectStore = transaction.objectStore("Imgs");
        const index = objectStore.index("imgUrl");
        const request = index.get(imgUrl);
        request.onerror = (event) => {
            reject("Error retrieving data from database");
        };
        request.onsuccess = (event) => {
            const data = event.target.result;
            // console.log(data);
            resolve(data?.imgCacheUrl);
        };
    });
}

remove db


const request = db
  .transaction(["customers"], "readwrite")
  .objectStore("customers")
  .delete("444-44-4444");
request.onsuccess = (event) => {
  // 削除完了!
};

update db

const objectStore = db
  .transaction(["customers"], "readwrite")
  .objectStore("customers");
const request = objectStore.get("444-44-4444");
request.onerror = (event) => {
  // エラー処理!
};
request.onsuccess = (event) => {
  // 更新したい、古い値を取得します。
  const data = event.target.result;

  // オブジェクト内の値を、希望する値に更新します。
  data.age = 42;

  // 更新したオブジェクトを、データベースに書き戻します。
  const requestUpdate = objectStore.put(data);
  requestUpdate.onerror = (event) => {
    // エラーが発生した場合の処理
  };
  requestUpdate.onsuccess = (event) => {
    // 成功 - データを更新しました!
  };
};

ref:

https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API/Using_IndexedDB
https://www.ruanyifeng.com/blog/2018/07/indexeddb.html