1

クライアント上のコレクションに挿入 (更新、削除など) する場合、ローカル オブザーバーは同期的に、つまり挿入の効果をローカルでシミュレートしながら起動します。これは、後続のコードが競合状態なしで挿入のすべての副作用に依存できることを意味します。

サーバー上の動作は異なるようです。オブザーバーは非同期的にトリガーされるようで、オブザーバーが実行される前に挿入コールバックが返される場合があります。これにより、コードを適切に同期することがより困難になります。挿入のすべての副作用がいつ発生したかを判断するための信頼できる方法が見つかりませんでした。クライアント以外では、挿入操作の直後に副作用に依存すると競合状態が発生し、クライアントとサーバー間でコードを共有することがより困難になります。

これは意図した動作ですか? すべてのオブザーバーがいつ実行されたかをサーバー側で通知するための適切な回避策はありますか?

(私の使用例: 元に戻す/やり直しに必要な「コマンド」テーブルがあります。新しいコマンドを挿入すると、ローカルの同期されていないコレクションへの変更がトリガーされます。つまり、コマンドはオブザーバー内から実行されます。後続のコマンドには、ローカル コレクションへの変更を完了する必要があります。そうしないと失敗します。)

4

1 に答える 1

1

私は流星の話グループで答えを見つけました。対応するコード コメントは次の場所にあります

// After making a write (with insert, update, remove), observers are
// notified asynchronously. If you want to receive a callback once all
// of the observer notifications have landed for your write, do the
// writes inside a write fence (set Meteor._CurrentWriteFence to a new
// _WriteFence, and then set a callback on the write fence.)

これが実際にどのように見えるか疑問に思われる場合に備えて、私が行ったことを (coffeescript で) 以下に示します。

Future = __meteor_bootstrap__.require('fibers/future')
...
future = new Future
fence = new Meteor._WriteFence
fence.onAllCommitted ->
  fence.retire()
  future.ret()
result = Meteor._CurrentWriteFence.withValue fence, ->
  # do something that triggers observers
  ...
  return result
fence.arm()
future.wait() # This will return only /after/ all observers fired.
...

これは文書化されていない機能であり、長期的に動作することは保証されていません。したがって、コア チームが公式の回避策を説明したい場合に備えて、私の質問は未解決のままです。

于 2013-02-11T00:39:20.810 に答える