javascript - Firebase Web SDK - Transaction causing on('child_added', func.. to be called -
see jsbin.com/ceyiqi/edit?html,console,output verifiable example.
i have reference listening database point
jobs/<key>
/list
where <key>
teams unique number
under entry point list of jobs
i have listener on point with
this.jobsref.orderbychild('archived') .equalto(false) .on('child_added', function(data) {
i have method following transaction:
ref.transaction(function(post) { // correct counter if(post) { // console.log(post); if(active) { // if toggeling on } else { // if toggeling off } } return post; })
when invoking transaction child_added
invoked again, giving me duplicate jobs.
is expected behavior? should check see if item has been got before , add array accordingly? or doing wrong?
thanks in advance time
you're hitting interesting edge case in how firebase client handles transactions. transaction function running twice, first on null
, on actual data. it's apparent see if listen value
events on /jobs, since you'll see:
- initial value
- null (when transaction starts , runs on
null
) - initial value again (when transaction runs again on real data)
the null
value in step 2 client's initial guess current value. since client doesn't have cached data /jobs (it ignores cached data /jobs/list), guesses null. wrong. unfortunately has been long time, it's unlikely change in current major version of sdk.
and because of null
in step 2, you'll child_removed
events (which you're not handling right now) , in step 3 you'll child_added
events re-add them.
if handled child_removed
events, you're items wouldn't end duplicated, still disappear / reappear, isn't desirable. workaround in current setup explicitly tell transaction not run local estimate, can passing in false
third parameter:
function transact() { var path = 'jobs/'; var ref = firebase.database().ref(path); ref.transaction(function(post) { return post; }, function(error, committed, snapshot) { if (error) { console.log('transaction failed abnormally!', error); } else if (!committed) { console.log('transaction aborted.'); } else { console.log('transaction completed.'); } }, false); }
i'm sorry don't have better solution. said: it's unlikely we'll able change behavior in current generation of sdks.
Comments
Post a Comment