I'm using web-sockets to transmit changes of a property, boardBucket
to other clients.
boardBucket
is a shared property of type Object
watched by an observer.
When the observer is notified of changes, the changes are sent via sockets to other clients where they are applied to their own boardBucket
.
The question now becomes how to prevent some object changes (via the Array mutation methods this.set()
, this.push()
etc.) from re-triggering that particular observer that sends the changes.
Without some-kind of silencing feature, the whole setup goes into an infinite round-trip between clients (one client changes boardBucket
, other client applies the changes but that also triggers it's own boardBucket
observer and resends them back on and on).
Is it possible to change the value of a property(or any of it's sub-items) without triggering a specific observer in some way?
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);
}
Ideally, a flag could be passed when mutating an Object/Array which can be picked up in the observers like so:
// 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");
}
Note :
<iron-signals>
(ie events) instead of observers but I'd prefer to avoid them, hence the question.boardBucket
is a property shared by multiple internal components with each component mutating and observing this. That's the reason I'm asking if only a specific observer can be skipped when mutating.changes
is the same then ignore it and not send it. However I'd like to have a way to prevent some other mutations from reaching the socket-send functions hence this won't work. It's also a tad hacky.I'd be interested to know what happens if you do something like this:
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 also seems a little hacky, my understanding of the limitations of this approach are as follows:
If (and only if) this.set
delivers exactly the changes passed to it before returning, then this should work. If it delivers any more changes, or delivers the changes it is passed asynchronously, then this won't work. Looking at the Polymer docs for Change notification protocol we have:
"When the property changes, the element fires a non-bubbling DOM event to indicate those changes to interested hosts."
Given a DOM event is used, I think it should be delivered before the this.set
call returns.
So I think the only mechanism for this going wrong would be if anything listening to the boardbucket decided to make changes in response to your change - I guess you should be in control of this for your app, and it seems like it would be a bad thing to have in any case. If this happened, I can't see that any response to it is valid; either you ignore these "changes in response to changes" and boardbucket becomes desynced between clients, or you send them through the socket and you are back to a potential cycle.
In more detail on this, if we refer to changes in response to changes as changes^2 then the code just prevents changes^2 being sent to the socket. If the changes^2 are meaningless to other clients then this is the correct behaviour. If the changes^2 are meaningful to other clients then they would need to be sent to the socket I guess, but this would be inefficient since it uses a loop through the network to update the data in a way that is presumably NOT in response to user input. I would guess such changes^2 would be better made by the client that sees the original changes - it could work out what changes^2 were needed in response to the existing changes it is about to send, and add them in to send through all at once. That way only one network transfer is needed, and any receiving clients know the data is valid and will not trigger any changes^2.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.