12

概要: WebページとWebワーカーの両方からIndexedDBにアクセスすることで、競合状態を回避しようとしています。

セットアップ: ユーザーがサイトで作業しているときにローカルのIndexedDBにアイテムを保存しているWebページ。ユーザーがローカルDBにデータを保存するたびに、レコードは「未送信」としてマークされます。

IndexedDBからデータをプルしてサーバーに送信し、サーバーがデータを受信すると、IndexedDB内のデータを「送信済み」としてマークするWebワーカーのバックグラウンドスレッド。

問題: IndexedDBへのアクセスは非同期であるため、Webワーカーがレコードをサーバーに送信すると同時にユーザーがレコードを更新しないことを保証できません。タイムラインを以下に示します。

  1. Web-workerはDBからデータを取得し、それをサーバーに送信します
  2. 転送が行われている間、ユーザーはデータを更新してDBに保存します。
  3. Webワーカーはサーバーから応答を取得し、DBを「送信済み」に更新します
  4. サーバーに送信されていないが「送信済み」とマークされたデータがDBにあります

失敗した解決策: サーバーから応答を受け取った後、行を再確認して、何かが変更されているかどうかを確認できます。ただし、データをDBに書き込むことができる小さなウィンドウがまだ残っており、サーバーにデータが送信されることはありません。

例:サーバーがデータが保存されたと言った後、次のようにします。

IndexedDB.HasDataChanged(
    function(changed) { 
        // Since this is async, this changed boolean could be lying.
        // The data might have been updated after I checked and before I was called.
        if (!changed){ 
          IndexedDB.UpdateToSent() }
    });

その他の注意事項: W3仕様に準拠した同期APIがありますが、まだ誰も実装していないため、使用できません(http://www.w3.org/TR/IndexedDB/#sync-database)。同期APIは、私が想定するこの正確な状況を回避するために、Webワーカーが使用するように設計されています。

これについての考えは大歓迎です。約1週間取り組んできましたが、うまくいくものを思い付くことができませんでした。

4

3 に答える 3

3

今のところ、この回避策を見つけたと思います。私が望むほどきれいではありませんが、スレッドセーフのようです。

データを更新するたびに、日時をLastEditフィールドに保存することから始めます。Webワーカーから、ブラウザーにメッセージを投稿しています。

self.postMessage('UpdateDataSent#' + data.ID + '#' + data.LastEdit);

次に、ブラウザで、最終編集日が変更されていない限り、送信済みフラグを更新しています。

// Get the data from the DB in a transaction
if (data.LastEdit == lastEdit)
{
    data.Sent = true;
    var saveStore = trans.objectStore("Data");
    var saveRequest = saveStore.put(data);
    console.log('Data updated to Sent');
}

これはすべてブラウザ側のトランザクションで行われるため、正常に機能しているようです。ブラウザがSyncAPIをサポートしたら、とにかくそれをすべて捨てることができます。

于 2012-01-28T16:27:17.787 に答える
0

トランザクションを使用できますか?
https://developer.mozilla.org/en/IndexedDB/IDBTransaction

于 2012-01-28T10:47:11.047 に答える
0

古いスレッドですが、トランザクションを使用すると、FailedSolutionアプローチが解決されます。つまり、トランザクションは、送信後にIndexedDB内のデータが変更されていないことを確認し、変更がない場合は送信済みとしてマークするだけで済みます。変更があった場合、トランザクションは書き込みなしで終了します。

于 2020-09-29T15:50:47.763 に答える