2016-11-22 24 views
1

フックを使用してオブジェクトにフィールドを追加する際に、オブジェクトが格納または変更されたときに、フィールドを追加する最適な方法を理解しようとしています。Dexie更新フックの非同期変更

基本的な考え方には、複雑なクエリと他のエントリの計算に基づいた多数のプロパティを含む必要があるオブジェクトがあります。entryがあります。計算されたこれらのプロパティは、すべてderivedというプロパティの下に格納されます。それが必要とされるたびに、またはDBから読み取られるときには、entry.derivedを計算するのは非常に高価です。代わりに、私はderivedプロパティを事前に設定することを選択し、フックはこれを行うのに最適な場所のようです。

これはcreatingフックでは問題ありません。しかし、entryの他のプロパティが変更された場合は、derivedを再生成する必要があります。 updatingフックでは、それらを返すことによって追加の変更を提出する必要があります。変更を生成できる唯一の方法は非同期呼び出しによるものであるため、問題があります。

以下は、問題を示す最小限のコードです。私はまだオプションBを試していないが、どちらもうまくいかないと思う。

答えて

1

残念ながら、フックは同期的であり、その中で非同期呼び出しを行う方法はありません。これは変わるつもりですが、私はいつ約束することはできません。次の6ヶ月以内にフック・フレームワークを書き直し、非同期(既存のフックの下位互換性を維持)できるバルク・フック(よりパフォーマンスの高いもの)を許可します。

これまでは、(ユーザーが明示的なトランザクションを行っているかどうかに関わらず)フックが常にトランザクション内で呼び出され、現在のトランザクションに対して追加の操作を行うことができます。あなたの追加の変更があなたのフックを再び引き起こすかもしれないので、あなたが無限ループに終わらないことを確認する必要があります。

の例では、このようになります:

db.entries.hook('creating', (primKey, entry, trans) => { 
    entryDerivedData(entry).then(derived => { 
     db.entries.update(primKey, { derived }).catch (e => { 
      // Failed to update. Abort transaction by rethrow error: 
      throw new Error ("Could not make sure derived property was set properly"); 
     }); 
    }); 
}); 

db.entries.hook('updating', (mods, primKey, entry, trans) => { 
    if ('derived' in mods) return; // We're the one triggering this change. Ignore. 
    // First, apply the mods onto entry: 
    var entryClone = Dexie.deepClone(entry); 
    Object.keys(mods).forEach(keyPath => { 
     if (mods[keyPath] === undefined) 
      Dexie.delByKeyPath(entryClone, keyPath); 
     else 
      Dexie.setByKeyPath(entryClone, keyPath, mods[keyPath]); 
    }); 

    entryDerivedData(entryClone).then(derived => { 
     db.entries.update(primKey, { derived }).catch (e => { 
      // Failed to update. Abort transaction by rethrow error: 
      throw new Error ("Could not make sure derived property was set properly"); 
     }); 
    }); 
}); 
関連する問題