2017-05-28 7 views
1

私はindexedDBをロードするクラスを持っています。クラスのメソッドがアクセスできるようになる前に、事前にindexedDBをロードする必要があります。現在私はthis.dbが初期化されていない他の方法よりも先にinit()メソッドを使用しています。クラス内で非同期のindexedDBを実装するためのきれいな方法

私は自分が持っているものを実装するためのよりクリーンな方法を探していますが、間違いなくDRYではありません。本質的にすべてのメソッドは現在以下のコードパターンで実装されています。

問題点である:

  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); 
     }; 
    }); 
    } 

答えて

2

のIndexedDB非同期機能を提供します。 indexedDB.openは非同期関数です。あなたは非同期的な方法でindexedDBを操作しようとしているようです。 IDBDatabase変数をクラスのインスタンスのプロパティとして格納する代わりに、それを解決値として返し、クラスの外部で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(); 
    } 
} 
+0

これを書いてくれてありがとうございました。私はあなたのポストからかなり学んだ!実際に、私は最終的に 'async/await'を初めて使用するようになりました:)。 – mythereal

関連する問題