How to prevent 'value' event on the client that issued set?

A Firebase client calling set() will cause all connected clients to have value triggered - including - the original client that issued the set().

In my case (and I think in most cases), there is no reason for the client that issued the set() to respond to the value event produced by its own call. Obviously its model is correct and there's no need to change it (which may be an expensive operation).

Is there any way for the client to not-receive/prevent/ignore the value event triggered by its own set() call ? I considered using off/on around set() but that can make the client miss value events that came at the same time but were not triggered by it.

Am I missing something obvious ?

Answers:

Answer

Most applications treat the Firebase data itself as their model. So when there's an update, they call ref.set() (or another mutator function) and then the update flows back into their app through an on() event. React/Flux aficionados know this as a unidirectional data-flow, other might know it as Command Query Responsibility Segregation.

But there indeed cases where the model has already been updated and thus you want to ignore the event from Firebase if you're the one who triggered it.

There is no API for not receiving theses self-triggered events. Instead you'll have to "remember" the data that you sent to Firebase and filter it out in your on() handler.

The Android drawing sample from Firebase keeps a list of segments that it sends to Firebase and then ignores those segments in its onChildAdded handler. It uses push ids to identify the line segments and those are generated client-side, so it can use those to track identify the segments.

A JavaScript sample of this:

var pendingChildIds = []; // Push ids of nodes we've sent to the server, but haven't received in `on()` yet

// this code is in your UI event handler, or whatever triggers the needs to update your Firebase data
var newChild = ref.push();
pendingChildIds.push(newChild.key());
newChild.set(
    { property1: 'value1', property2: 3.14 },
    function(error) {
        // the write operation has completed, remove the child id from the list of pending writes
        pendingChildIds.splice(pendingChildIds.indexOf(newChild.key());
    }
);

// this is the event handler, using child_added in this case
ref.on('child_added', function(snapshot) {
    if (!pendingChildIds.contains(snapshot.key())) {
        // this is a child that we DIDN'T generate
    }
});
Answer

I ended up adding a client ID to the model, something like:

var clientId=(Math.random()*10000000000000000).toFixed(0);

function set(data) {
    ref.set(JSON.stringify({ clientId: clientId, data: data }));
}

ref.on('value', function(snapshot) {
    var json=JSON.parse(snapshot.val());
    if (!json || json.clientId===clientId) return;

    var data=json.data;
    // update model with data
});

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.