8

Observable をグループ化し、各 GroupedObservable から最後に発行されたアイテムのみをメモリに保持する方法は? 各グループが BehaviorSubject と同じように動作するようにします。

このようなもの:

{user: 1, msg: "Anyone here?"}
{user: 2, msg: "Hi"}
{user: 2, msg: "How are you?"}
{user: 1, msg: "Hello"}
{user: 1, msg: "Good"}

したがって、メモリには、それぞれの最後のアイテムしかありませんuser

{user: 2, msg: "How are you?"}
{user: 1, msg: "Good"}

サブスクライバーがサブスクライブすると、これら 2 つのアイテムがすぐに発行されます (それぞれが独自の発行で)。それぞれに BehaviorSubject があったようにuser

onCompleted() は、人々が永遠にチャットする可能性があるため、起動することは想定されていません。

userどのような値が存在する可能性があるかは事前にわかりません。

4

2 に答える 2

3

あなたのチャットログのオブザーバブルはホットだと思います。したがって、#groupBy によって発行された groupObservables もホットになり、それ自体では何もメモリに保持されません。

必要な動作を取得するには (サブスクリプション前の最後の値を除くすべてを破棄し、そこから続行します)、ReplaySubject(1) を使用できます。

間違っていたら訂正してください

jsbinを参照してください

var groups = chatlog
      .groupBy(message => message.user)
      .map(groupObservable => {
        var subject = new Rx.ReplaySubject(1);
        groupObservable.subscribe(value => subject.onNext(value));
        return subject;
      });
于 2015-12-08T18:32:59.130 に答える
2

グループ化されたオブザーバブルの最新の発行されたアイテムを明らかにする削減関数を記述し、それをオブザーバブルに渡し、新しいサブスクライバーに対して発行された最後の値を呼び出すためにscan使用できます。shareReplay次のようになります。

var fn_scan = function ( aMessages, message ) {
  // aMessages is the latest array of messages
  // this function will update aMessages to reflect the arrival of the new message
  var aUsers = aMessages.map(function ( x ) {return x.user;});
  var index = aUsers.indexOf(message.user);
  if (index > -1) {
    // remove previous message from that user...
    aMessages.splice(index, 1);
  }
  // ...and push the latest message
  aMessages.push(message);
  return aMessages;
};
var groupedLatestMessages$ = messages$
    .scan(fn_scan, [])
    .shareReplay(1);

したがって、サブスクライブするたびに得られるのは、その時点でのサイズがメッセージを送信したユーザーの数であり、コンテンツがユーザーによって送信されたメッセージを送信時間順に並べた配列です。

サブスクリプションがあるときはいつでも、最新の配列がすぐにサブスクライバーに渡されます。それは配列ですが、仕様を満たすと同時に値を1つずつ渡す方法は考えられません。あなたのユースケースにはそれで十分であることを願っています。

更新:jsbinはこちらhttp://jsfiddle.net/zs7ydw6b/2

于 2015-12-08T01:15:45.227 に答える