在类中实现异步索引数据库的简洁方法

myt*_*eal 1 javascript indexeddb

我有一个加载indexedDB 的类。在类中的方法可以访问它之前,我需要预先加载indexedDB。目前,我使用的init()方法先于任何其他未this.db初始化的方法。

我正在寻找一种更干净的方法来实现我所拥有的,这绝对不是干的。基本上每个方法目前都是使用下面相同的代码模式实现的。

问题点是:

  1. 需要另一种方法init()才能正确处理indexedDB的初始化。
  2. 这个if (!this.db) {片段稍后会重复出现。

export default class Persist {
  constructor(storage) {
    if (storage) {
      this.storage = storage;
    }
    else {
      throw new Error('A storage object must be passed to new Persist()');
    }
  }

  // needed to ensure that indexedDB is initialized before other methods can access it.
  init () {
    // initialize indexedDB:
    const DBOpenRequest = this.storage.open('db', 1);

    DBOpenRequest.onupgradeneeded = () => {
      const db = DBOpenRequest.result;
      db.createObjectStore('db', { keyPath: 'id', autoIncrement: true });
    };

    return new Promise((resolve, reject) => {
      DBOpenRequest.onerror = event => {
        reject(event);
      };

      DBOpenRequest.onsuccess = event => {
        console.log(`IndexedDB successfully opened: ${event.target.result}`);
        resolve(event.result);
        this.db = DBOpenRequest.result;
      };
    });
  }

  toStorage(session) {
    if (!this.db) {
      return this.init().then(() => {
        const db = this.db;
        const tx = db.transaction('db', 'readwrite');
        const store = tx.objectStore('db');
        const putData = store.put(session.toJS());

        return new Promise((resolve, reject) => {
          putData.onsuccess = () => {
            resolve(putData.result);
          };

          putData.onerror = () => {
            reject(putData.error);
          };
        });
      });
    }

    // basically a repeat of above
    const db = this.db;
    const tx = db.transaction('db', 'readwrite');
    const store = tx.objectStore('db');
    const putData = store.put(session.toJS());

    return new Promise((resolve, reject) => {
      putData.onsuccess = () => {
        resolve(putData.result);
      };

      putData.onerror = () => {
        reject(putData.error);
      };
    });
  }
Run Code Online (Sandbox Code Playgroud)

Jos*_*osh 5

indexedDB 提供异步功能。indexedDB.open是一个异步函数。看起来您正在尝试以非异步方式使用indexedDB。无需将 IDBDatabase 变量存储为类实例的属性,只需将其作为解析值返回并在类外部进行管理即可。

function connect(name, version) {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(name, version);
    request.onupgradeneeded = myUpgradeHandlerFunction;
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
    request.onblocked = () => { console.log('blocked'); };
  });
}

function doStuffWithConn(conn, value) {
  return new Promise((resolve, reject) => {
    const tx = conn.transaction(...);
    const store = tx.objectStore(...);
    const request = store.put(value);
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
}

async function putValue(value) {
  let conn;
  try {
    conn = await connect(...);
    await doStuffWithConn(conn, value);
  } catch(exception) {
    console.error(exception);
  } finally {
    if(conn)
      conn.close();
  }
}
Run Code Online (Sandbox Code Playgroud)