2016-03-27 5 views
2

私はウェブソケットを使用して、他のクライアントにboardBucketというプロパティの変更を送信しています。特定のオブザーバをトリガーしない配列の変異

  • boardBucket観察者が見タイプObjectの共有財産です。

  • 変更がオブザーバに通知されると、変更はソケットを介して他のクライアントに送信され、そこで自分自身のboardBucketに適用されます。

問題は今変更を送信し、その特定のオブザーバを再トリガから(Array mutation methodsthis.set()this.push()などを介して)いくつかのオブジェクトの変更を防止する方法になります。機能をサイレンシングの一部現物なし

、全体のセットアップは1つのクライアントがboardBucketを変更する(クライアント間で無限の往復になり、他のクライアントは、変更が適用されますが、それはまた、それ自身のboardBucketオブザーバをトリガし、背中にそれらを再送しますと)。


それは、プロパティの値(またはその任意のサブ項目をだ)何らかの方法で特定のオブザーバーをトリガなしに変更することは可能ですか?

// flag can be read in observer 
    _boardBucketChanged: function(changes, flag) { 
     if(flag === "preventNotify") return false; 
     sockets.send(changes); 
    }, 

    // `flag` parameter can be passed with each mutation 
    _boardBucketReceived: function(changes) { 
     if(flag === "preventNotify") 
     return false; 
     this.set("boardBucket", changes, "preventNotify"); 
    } 

  • 私ができるようように観察者に撮像することができるオブジェクト/配列を変異させる場合

    properties: { 
         boardBucket: { 
         type: Object, 
         value: null, 
         notify: true 
         } 
        }, 
    
        observers: [ 
         "_boardBucketChanged(boardBucket.*)" 
        ], 
    
        // if my `boardBucket` changes send changes to other clients 
        _boardBucketChanged: function(changes) { 
         sockets.send(changes); 
        }, 
    
        // get changes sent by other clients and apply them 
        _boardBucketReceived: function(changes) { 
    
         // How can I silently make the following changes 
         // so it doesn't trigger **only** the above observer? 
         this.set("boardBucket", changes); 
        } 
    

    理想的には、フラグを渡すことができまた、オブザーバーの代わりに<iron-signals>(すなわちイベント)を使用してくださいが、私はそれらを避ける方がよいでしょう。

  • boardBucketは、複数の内部コンポーネントによって共有されるプロパティで、各コンポーネントはこれを変更して監視します。これは、の特定のオブザーバだけが突然変異するときにスキップできるかどうかを尋ねる理由です。
  • 受信/送信の変更の間にいくつかの等価性チェックを行い、パス/値がchangesの場合、それを無視して送信しないことができます。しかし、私はいくつかの他の突然変異がsocket-send関数に到達するのを防ぐ方法を持っていますので、これはうまくいきません。それはまた、ちょっとしたハッキーです。

答えて

1

私はあなたがこのような何かをすれば何が起こるかを知って興味があると思います:

properties: { 
    boardBucket: { 
    type: Object, 
    value: null, 
    notify: true 
    }, 
    settingBucket: { 
    type: Boolean, 
    value: false 
    } 
}, 

observers: [ 
    "_boardBucketChanged(boardBucket.*)" 
], 

// if my `boardBucket` changes send changes to other clients 
_boardBucketChanged: function(changes) { 
    //If we're setting, this is our change. 
    //TODO: Is there any way that we can receive a change while 
    //setting that is NOT the result of calling this.set? For 
    //example if changes are batched and sent at once? 
    if (!this.settingBucket) sockets.send(changes); 
}, 

// get changes sent by other clients and apply them 
_boardBucketReceived: function(changes) { 
    //We are currently setting bucket, so ignore received changes 
    this.settingBucket = true; 
    this.set("boardBucket", changes); 
    //Now we're done 
    this.settingBucket = false; 
} 

また、これは、このアプローチの限界を私の理解、少しハックようだ次のとおりです。

this.setが返される前に渡された変更を正確に配信する場合は、これが有効になります。それ以上の変更を提供する場合、または変更を配信する場合、非同期に渡されますが、これは機能しません。 Polymer docs for Change notification protocolを見ると:

"プロパティが変更されると、要素は興味のあるホストへの変更を示す非バブリングDOMイベントを発生させます。"

DOMイベントが使用されているとすれば、this.setコールが返される前に配信する必要があると思います。

ボードバケットを聞いている人があなたの変更に応じて変更を加えることを決めた場合、これが間違っている唯一のメカニズムだと思います。あなたのアプリのためにこれを制御する必要がありますいずれにしても悪いことではありません。これが起こった場合、私はそれに対する応答が有効であることを見ることができません。これらの "変更に対する応答の変更"を無視するか、またはボードバケットがクライアント間で非同期になるか、ソケットを介して送信すると、潜在的なサイクルに戻ります。

これについてさらに詳しく説明すると、変更が変更^ 2として変更に反映された場合、コードはソケットへの変更^ 2の送信を防ぎます。^2の変更が他のクライアントにとって無意味な場合、これは正しい動作です。^2の変更が他のクライアントにとって意味のあるものであれば、それらはソケットに送信する必要がありますが、これはネットワーク経由のループを使用して、おそらく応答しない方法でデータを更新するので非効率ですユーザ入力。私はこのような変更を^ 2がオリジナルの変更を見るクライアントによってうまくいくだろうと思うでしょう - あなたが送信しようとしている既存の変更に応じて^ 2の変更が必要であるかどうかを確認し、すぐに。そうすれば、1回のネットワーク転送だけが必要となり、受信側のクライアントはデータが有効であることを知り、変更を引き起こさないでしょう^ 2。

+0

ニース:)実際には、これは*インタロック*になっています。しかし、設定が完了している間に*新しい*変更が来たらどうなるでしょうか?実際の問題は、あなたがすでに指摘した問題ですが、このメカニズムは 'this.set()'に応答してどのような変更も禁止しますので、少し柔軟性がありません。 –

+0

_boardBucketReceivedが何とか再帰的に(this.setに応答して)呼び出すことができない限り、設定が行われている間に新しい変更が発生することは間違いないと思います。 WebSocketからの単なるコールバックだと仮定すると、一度に1回だけ呼び出されるべきです。 – trepidacious

関連する問題