2016-11-14 4 views
2

複数の読み取り/書き込みをIndexedDBにするSPAアプリケーションがあります。 DBを開く毎回IDBデータベースを開くか、1つのインスタンスを開いたままにする必要がありますか?

がコールバックとは非同期操作です:

var db; 
var request = window.indexedDB.open("MyDB", 2); 

request.onupgradeneeded = function(event) { 
    // Upgrade to latest version... 
} 

request.onerror = function(event) { 
    // Uh oh... 
} 

request.onsuccess = function(event) { 
    // DB open, now do something 
    db = event.target.result; 
}; 

私はこのdbインスタンスを使用できる2つの方法があります。

  1. は、ページの人生のために単一dbインスタンスをキープ/スパ?
  2. 現在の操作が完了したらdb.close()にコールし、次の操作で新しいものを開きますか?

は、どちらかのパターンの落とし穴がありますか? indexedDBを開いたままにしておくと、リスクや問題はありますか?それぞれのopenアクションにオーバーヘッド/遅延がありますか?

答えて

3

たびにブラウザがより多くの仕事をしているという理由だけ遅くなる可能性が高い接続を開く(例えばそれは、ディスクからデータを読み取るために必要がある場合があります)。さもなければ、本当のダウンサイドはありません。

アップグレードについて言及しているので、いずれのパターンでも、ユーザーが別のタブでページを開き、より新しいバージョンのデータベースを開くようにします(サーバーから新しいコードをダウンロードしたため)。以前のタブがバージョン3で、新しいタブがバージョン4であるとします。

操作1回あたりのケースでは、別のタブでバージョン3のopen()が失敗しましたバージョン4にアップグレードすることができます。オープンがVersionErrorで失敗したことに気付くことができます。ユーザーにページを更新する必要があることを通知します。

1接続あたりのページの場合には、バージョン3での接続は、他のタブをブロックします。 v4タブは、リクエストの"blocked"イベントに応答し、古いタブを閉じるべきことをユーザーに知らせることができます。または、v3タブで接続のversionupgradeイベントに応答し、ユーザーに終了する必要があることを伝えることができます。または両方。

+0

乾杯、これはちょうど私が知る必要がある種類のものです。私は複数のタブをサポートしたいと思いますが、サービスワーカーも使用していますので、1つのタブが別のバージョンを取得するシナリオを取るべきではありません。より懸念されるのは、あるタブの接続が別のタブをブロックしていることです。これは、特に避けたいものです。 – Keith

2

私は、操作ごとに接続を開いてもパフォーマンスが大幅に低下しないことが分かりました。私は1年以上前からローカルのChrome拡張機能を実行してきましたが、これには大量のindexedDB操作が含まれており、何百回ものパフォーマンスを分析しており、接続をボトルネックとして開くことはありませんでした。ボトルネックは、索引を適切に使用しないか、大きなブロブを格納するようなことをします。

基本的に、この決定はパフォーマンスに基づいて行わないでください。接続という点では本当に問題ではありません。

実際にあなたのコードの人間工学、APIとの戦いの程度、コードを見てどのように直感的に感じるのか、コードがどれほど控えめであるのか、新鮮な目を歓迎するのか(1ヶ月後、または他の誰かのあなた自身のもの)。これは間接的にアプリケーションモダリティを扱っているブロッキングの問題に対処する際に非常に顕著です。

私の個人的な意見は、JavaScriptの非同期書き込みに慣れている場合は、あなたが好みの方法で使用することです。非同期コードで苦労している場合は、常に接続を開くことを選択することで問題が回避される傾向があります。私は、非同期コードの方が新しい人に、1つのグローバルページライフタイム変数を使用することを決して勧めません。また、ページの存続期間中に変数をそこに残しています。一方、非同期であることがわかり、グローバルdb変数をより受け入れやすいものにするには、是非それを使用してください。

編集 - あなたのコメントに基づいて、私は私が私の個人的な好みのいくつかの擬似コードを共有するだろうと思った:

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

async foo(bar) { 
    let conn; 
    try { 
    conn = await connect(DBNAME, DBVERSION); 
    await storeBar(conn, bar); 
    } finally { 
    if(conn) 
     conn.close(); 
    } 
} 

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

非同期で/のawait、自分の業務に余分なconn = await connect()ラインを持つことにあまりにも多くの摩擦がありません機能。

+0

私は、ES6で 'async'と' await'で使うことができるPromiseベースのAPIにindexedDBをラップすることを計画していますが、私はあなたのことを思い浮かべます - グローバル変数と非同期の組み合わせ。 – Keith

関連する問題