1

Firebase for Android では、スロット数が制限されたチャット ルームに次のデータ構造を使用しています。

/rooms
  /<roomid, generated by push()>
    /users
      one: null
      two: null
      three: null

クライアントがスロットの 1 つ ( oneto 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つの仮定は正しいですか?

  1. ( runTransaction(...)Android) またはtransaction(...)(JavaScript) では、オプションのパラメーターfireLocalEvents(Android) またはapplyLocally(JavaScript) をに設定する必要falseがあります。そうしないと、トランザクションからイベントを受け取ることになりますが、成功しない可能性があります。
  2. fireLocalEvents(Android) またはapplyLocally(JavaScript) が に設定されていても、トランザクションが で正常に返される前に、その参照falseのイベントが発生します。これは意図した動作ですか?onChildChanged(...)onComplete(...)

この特殊なケースでこれが意味することは、チャット ルームが満員であることを通知され ( でChildEventListener.onChildChanged(...)) 、自分が最後のスロットを獲得したことを知るに ( で) ということです。Transaction.Handler.onComplete(...)

仮に部屋が満室だったら…

  • そこにスロットがあり、いくつかのコードが実行され、何か新しいものが起動されます。
  • スロットを取得できませんでした。リストから部屋を非表示にしたいだけです(もう利用できないため)。

それをしたい場合は、そのための完全なロジックを に移動する必要がありChildEventListener.onChildChanged(...)ます。最初にイベントを受け取る場所だからですよね? そうしないと、部屋の最後のスロットを獲得したのが私であることがわかる前に、部屋が隠されます。

何か案は?

4

1 に答える 1

1

これは実際、Firebase を素晴らしいアプリにし、大量のコーディングを節約するコンポーネントの 1 つです。これがあなたの利益になる理由を理解するために、少し戻ってレイテンシー補正とオフライン機能について話す必要があります.

リアルタイム機能を提供するアプリを作成したことがある場合は、接続エラーと一時的な停止のスパゲッティの混乱に遭遇したことがあります。接続が復元されると、大量の if/else/then ロジックが再試行されます。

Firebase はこの複雑さをすべて抽象化するため、アプリはオンライン時と同じようにオフラインでも動作します。イベントをリッスンしたり、データを設定/保存/更新したり、オンラインのように続行したりできます。接続が復元されると、イベントが適用されます。

同様に、ローカルで set() 操作を行う場合、変更をローカルに適用する前にサーバーが応答するのを待つのは非常に時間がかかります。繰り返しますが、これは遅延補償のための多くの if/else ロジックにつながります。ローカルで変更を行ったときに追跡し、すぐに表示して、ユーザーがアプリが応答していないように感じないようにします。

Firebase は、これらの複雑さを内部で処理します。実稼働環境での書き込み操作の 99.9% は成功するため、無効なコンテンツの送信は一般にバグが原因であるため、正しいイベントを発生させて変更をローカルに適用するだけです。次に、サーバーがその極端なケースで応答した場合、ステータスを修正する別のイベントを適用して変更を編集します。

つまり、変更を加えた場合、Firebase データは最終的に一貫性があります。したがって、ローカル イベントがすぐに表示されます。これは良いことです。プロセスで何か問題が発生した場合、おそらく数百ミリ秒後に、データを修正するための 2 番目のイベントが表示されます。

于 2014-10-14T15:51:02.413 に答える