Listen to updates
var node = gun.get('watcher/f0de26c0-a29f-11e7-8661-154b982951a4')
node.get('stats').on(function (v, k) {
console.log('v:', v);
console.log('k:', k);
});
Update
node.put({
stats: {
num: 3
},
name: 'trex'
});
If you update the node
with the same object multiple times, every time there is the update on the listener side.
{"_":{"#":"j94c5jht6u6KTIoltGt7mHx",">":{"num":1508935385873.435}},"num":3}
{"_":{"#":"j94c5jht6u6KTIoltGt7mHx",">":{"num":1508935385873.435}},"num":3}
{"_":{"#":"j94c5jht6u6KTIoltGt7mHx",">":{"num":1508935386550.19}},"num":3}
How to receive update only if a property value was changed?
var gun = new Gun();
var result = document.getElementById('result');
var node = gun.get('watcher/f0de26c0-a29f-11e7-8661-154b982951a4');
node.get('stats').on(function (v, k) {
displayValue(v);
console.log('v:', v);
console.log('k:', k);
});
function displayValue (v) {
var p = document.createElement("p");
var t = document.createTextNode(JSON.stringify(v));
p.appendChild(t);
result.appendChild(p);
};
function createNode () {
node.put({
stats: {
num: 3
},
name: 'trex'
});
}
function updateNode() {
node.put({
stats: {
num: 3
},
name: 'trex'
});
}
function deleteNode() {
while (result.firstChild) {
result.removeChild(result.firstChild);
}
}
var createNodeBtn = document.getElementById('create_node');
createNodeBtn.onclick = createNode;
var updateNodeBtn = document.getElementById('update_node');
updateNodeBtn.onclick = updateNode;
var deleteNodeBtn = document.getElementById('delete_node');
deleteNodeBtn.onclick = deleteNode;
<script src="https://rawgit.com/amark/gun/master/gun.js"></script>
<button type="button" id="create_node">create</button>
<button type="button" id="update_node">update</button>
<button type="button" id="delete_node">clean</button>
<div id=result></div>
@trex ,
There are two things here:
These are two very different things. Lets look at them.
A 2nd update, even if it is the same data, is still considered a new update. Here is an important example of why:
foo
as 1
.foo
as 2
.foo
as 1
AGAIN before she hears Bob's update (because of latency).THEN Alice will discard Bob's update, because Alice saved the same data again at a more recent time. So while this does not look like a change to Alice, it is a legitimate change that all peers need to process.
Because the above is important, gun will not by default deduplicate this. You would have to deduplicate it yourself using some simple logic like this:
var was;
gun.get('some').get('data').on(function(data, key){
if(was === (was = data)){ return }
cb(data, key);
});
Note: JS primitives can be
===
, but ifdata
is an object (a node in gun) then you'd need to add some extra logic to do a deep-comparison, probably using a utility library like lodash or underscore.
The extra-overhead logic is actually another reason why gun does not do this by default, because not all apps need this behavior. For apps (like yours) that need this behavior, it is easy to customize your gun with this extension:
Gun.chain.uniqueUpdates = function(cb){
var was;
return this.on(function(data, key){
/* your deduplication/deep-comparison logic here */
cb(data, key);
});
}
Now you can replace using on in your app with your new module!
gun.get('some').get('data').uniqueUpdates(cb);
You can easily apply the above mentioned technique (of stopping observable changes) and it will also stop gun from firing with duplicate data.
Why does gun fire with duplicate data, when there are no changes?
GUN actually deduplicates updates at the root of the graph, however the chaining API unfortunately does not currently (v0.8.9) deduplicate. This means if you were to externally send gun "old" data it would deduplicate it. However, internal mechanisms of the chaining API are extraordinarily complex, when we tried to add deduplication there it caused more bugs than the inconvenience of duplicate messages on an event emitter (which already has to be designed to handle multiple messages).
That said, we plan to fix this after GUN is stable and production ready, as it is a constant nuisance for me and new developers. It is technically not wrong behavior, but it is unnecessary/annoying, and thus has 0 priority for now.