Firebase for Android では、スロット数が制限されたチャット ルームに次のデータ構造を使用しています。
/rooms
/<roomid, generated by push()>
/users
one: null
two: null
three: null
クライアントがスロットの 1 つ ( one
to three
) を取得するために、ここで提供されている次のコード(JavaScript バージョン)を使用しています。
var userid = "myuserid";
var ref = new Firebase("<my-firebase>.firebaseio.com/rooms/<roomid>/users");
ref.transaction(function(users) {
if (!users.one) {
// Claim slot 1
users.one = userid;
return users;
} else if (!users.two) {
// Claim slot 2
users.two = userid;
return users;
} else if (!users.three) {
// Claim slot 3
users.three = userid;
return users;
}
// Room is full, abort the transaction.
return;
}, function(err, committed, snapshot) {
if (committed && !err) {
// Joined room successfully.
} else {
// Could not join room because it was full.
}
});
いくつかのテストの後、これは機能しないことがわかりました。それが機能しない理由を説明する次の2つの仮定は正しいですか?
- (
runTransaction(...)
Android) またはtransaction(...)
(JavaScript) では、オプションのパラメーターfireLocalEvents
(Android) またはapplyLocally
(JavaScript) をに設定する必要false
があります。そうしないと、トランザクションからイベントを受け取ることになりますが、成功しない可能性があります。 fireLocalEvents
(Android) またはapplyLocally
(JavaScript) が に設定されていても、トランザクションが で正常に返される前に、その参照false
のイベントが発生します。これは意図した動作ですか?onChildChanged(...)
onComplete(...)
この特殊なケースでこれが意味することは、チャット ルームが満員であることを通知され ( でChildEventListener.onChildChanged(...)
) 、自分が最後のスロットを獲得したことを知る前に ( で) ということです。Transaction.Handler.onComplete(...)
仮に部屋が満室だったら…
- そこにスロットがあり、いくつかのコードが実行され、何か新しいものが起動されます。
- スロットを取得できませんでした。リストから部屋を非表示にしたいだけです(もう利用できないため)。
それをしたい場合は、そのための完全なロジックを に移動する必要がありChildEventListener.onChildChanged(...)
ます。最初にイベントを受け取る場所だからですよね? そうしないと、部屋の最後のスロットを獲得したのが私であることがわかる前に、部屋が隠されます。
何か案は?