2017-07-08 3 views
0

「child_added」、「child_changed」、「child_removed」、および「value」という概念に精通しています。 リストを使うと、動的に更新されるはずですが、「値」を除くすべての関数を使用し、データの静的なスナップショットが必要なときは常に「値」を使用します。child_addedを効率的に使用する方法

次のように私の質問は:

は、それは本当に(あなたが「child_moved」数える場合4)私はリストを持っているときは常に3つのトリガを書くための最良の方法ですか?単純なアプリにはたくさんのリストがあります。 はいの場合、javascriptで最も効率的な方法でどのように処理されますか?私の現在のアプローチは以下の通りです:

  • on child_added:私のリスト全体を繰り返します。キーがイベントから受け取ったキーと等しいかどうかを調べ、oldValueの値を保存します。リストからmyList [myList.indexOf(oldValue)]を削除しながら、prevChildKeyのインデックスを見つけて、直前に受信した子をprevChildKeyのインデックスの後に挿入します。
  • on child_changed:リスト全体を繰り返します。キーがイベントから受け取ったキーと等しいかどうかを調べ、oldValueの値を保存します。セットmyList [myList.indexOf(oldValue)] = newValue;
  • on child_removed:myList.splice(...)と同じだけです。
  • on child_moved:私はこれを実装していません。しかし、私はおそらくそれが必要になります、child_changedが呼び出され、これは私の要素の変更の順​​序になりました。ですから、child_addedに非常に類似したロジックがあります

これをより洗練された方法で処理する方法はありますか?私は最初にmyList [child.key]で要素にアクセスしようとしましたが、これは私のためには機能しません。

編集:追加コード自分のアプリケーション内のすべてのリストについては、

myRef.orderByChild("timestamp").on("child_added",(message,prevChildKey) => { 
     //Transform the firebase-date into my own format 
     var template = { 
      senderName: message.val().sender, 
      time: message.val().timestamp, 
      id: message.key} 

     //Check where to add this 
     if(prevChildKey){ 
      this.messages.forEach(currentMessage => { 
       if(currentMessage.id === prevChildKey){ 
        var indexToAdd = this.messages.indexOf(currentMessage); 
        this.messages.splice(indexToAdd+1,0,template]; 
       } 
      }); 
     }else 
      this.messages.unshift(template); 

}); 
myRef.on("child_changed", message => { //orderByChild makes no sense here, right ? 
    //Transform the firebase-date into my own format 
    var template = { 
     senderName: message.val().sender, 
     time: message.val().timestamp, 
     id: message.key} 

    var toBeUpdated = undefined; 
    this.messages.forEach(currentMessage => { 
     if(currentMessage.id === message.id){ 
      this.messages[this.messages.indexOf(currentMessage)] = template; 
     } 
    }) 

    //How do I preserve ordering here, since I was ordering by timestamp on child_added before and I don't check if that value changed 
} 
myRef.on("child_removed", oldMessage => { 

    //Remove the message 
    this.messages.forEach(currentMessage => { 
     if(currentMessage.id === oldMessage.id){ 
      this.messages.splice(this.messages.indexOf(currentMessage),1); 
     } 
    }) 
} 
myRef.orderByChild("timestamp").on("child_moved", (message,prevChildKey) => { //Not too sure, how this works. Do I need the orderByChild here to preserve it ? 

    var messageToMove = undefined; 
    var messagePosition = undefined; 
    var indexToMoveTo = undefined; 
    this.messages.forEach(currentMessage => { 
     if(currentMessage.id === message.id){ 
      messagePosition = this.messages.indexOf(currentMessage); 
      messageToMove = this.messages[messagePosition]; 
     } 
     if(currentMessage.id === prevChildKey){ 
      indexToMoveTo = this.messages.indexOf(currentMessage) + 1; 
     } 
    }) 

    //Remove the message from where it was 
    this.messaged.splice(messagePosition,1); 
    //Add the message at the new position 
    this.messages.splice(indexToMoveTo,0,messageToMove); 

} 
+0

もっと効率的なやり方があるかどうかを尋ねてきます。私たちの多くは、コードの説明を解析するのが得意ではありません。だから、[あなたの現在のソリューションを示す最小限の実際のコード](http://stackoverflow.com/help/mcve)を投稿してください。おそらくもっと助けることができます。 –

+0

デモンストレーションとしていくつかのコードを追加しました – Thomas

+0

ユースケースの説明は少し不明です。 *なぜ*キーがあなたが今受け取ったキーと同じかどうかを確認するためにリストを反復していますか?あなたは投稿を注文し続けようとしていますか?もしそうならば、各投稿にタイムスタンプを付けるだけで、いつも正しい順序で表示されます。また、投稿が追加、変更、削除された場合、特定の投稿がアプリに渡され、そのノードに直接アクセスできるようになります。リストを繰り返して検索する必要はありません。つまり、node_3が変更された場合、そのキー(node_3)がアプリに渡され、node_3/child_nodesに直接アクセスして更新できます。 – Jay

答えて

0

を適用するために、多くのコードを、それを実証するだから私は何とか私は私の地元にfirebaseから取得する要素をマップする必要がありますそれの の表現。

ああ!それは簡単です!

ご存じの通り、Firebaseはキーと値のペアでデータを保存します。あなたはノードに名前を変更した場合

したがって、たとえば、ユーザノードが

users 
    uid_0 
     name: "Bill" 
    uid_1 
     name: "Larry" 

なり、ビルはビリーに、uid_0ノード(子データ)が中にあなたのアプリケーションに渡されると言いますスナップショットであり、キーはuid_0です。そのキーは、配列に格納されているデータに対応します。

これについてはさまざまな方法があります。

1つの方法は、オブジェクトをキー値のペアの辞書として配列に格納することです。いくつかの疑似コード..

myDictionary = [ "uid_0": [name: "Billy"] ] 
myArray[0] = myDictionary 

しかし、それを行うための「classier」方法は、クラスのプロパティのいずれか

UserClass { 
    key = "" 
    name = "" 
} 

let aUser = UserClass 
aUser.key = snapshot.key 
aUser.name = snapshot.value("name") //loose pseudo code, dont copy/paste! 

myArray[0] = userClass 
などのユーザクラスを作成し、キー(uid_0)と、配列内のそれらを格納することであろうあなたのアプリがスナップショットを受信したとき

はその後、あなたはすべてがFirebaseが保存され、キーを介してアクセスされていることであるsnapshot.key

大局から受信userClass.keyの配列を照会することができ、それは一貫性のままで、変わらないので、あなたの友人を守るために使うツールです(メッセージs)配列はFirebaseと同期します。

編集:ソートされた配列オブジェクトに直接アクセスするには、キーと要素番号をHashMap(辞書)に格納します。その後、

Map<String, String> map = new HashMap<String, String>(); 
map.put("uid_0", "0"); 

は、インデックスを出力uid_0

System.out.println(map.get("uid_0")); 

するためのインデックスを印刷するには:0

あなただけの1つのストレージメカニズム、TreeMapの(自然な順序)、または使用する場合LinkedHashMapは移動する方法です。

map.put("uid_0", *values for uid_0, name etc*); 
+0

答えをくれてありがとうございますが、snapshot.keyの対応するuserClass.keyを見つけるにはまだ繰り返しますそれを見つけるために私の配列。私はしない?これは、私の現在のアプローチであり、クラスなしです。一致するuserClass.keyを常に見つけて、順序を維持することは、まだ多くのコードです(私の投稿に示されています)。 – Thomas

+0

私は謝罪しました。私は、スナップショットを活用して背景を整理するために、高いレベルで話していました。私は詳細を答えを更新しました - あなたがデータを読み込んだときにFirebaseによってデータが注文され、LinkedHashMapがその注文を維持し、snapshot.key要素に直接アクセスできるようにするために、LinkedHashMapをストレージとして活用することをお勧めします。 – Jay

+0

私もこれを考えていました。しかし、まず、私が知る限り、JavaScriptはLinkedHasMapsをサポートしていません。注文を保持しないディレクトリのみ。もう1つのポイントは、ビュー内で* ngFor(Angularの場合)がMapsを反復処理できないことです。だから私は配列としてキーを提供し、キーで私のディレクトリ内の正確なエントリを参照して別の関数を記述する必要があります。悲しいことは、私がオンラインで見つけたすべてのチュートリアルは、単純化のためにchild_ *(child_addedを除く)イベントを無視することです。しかし、これをjavascript(またはtypescript)で解決するにはスムーズな方法が必要です。 – Thomas

関連する問題