2

My firebase looks like this:

enter image description here

This is test code (coffee script):

Firebase = require 'firebase'

ref = new Firebase 'https://my_firebase.firebaseio.com/items'

ref.once 'child_added', (snapshot) ->
  childRef = snapshot.ref()
  console.log "child_added", childRef.toString(), snapshot.val()
  childRef.transaction(
    (data) ->
      console.log 'transaction on data', data
      return if !data or data.my_key isnt 'my_val'
      data.my_key = 'new_val'
      return data
    ,
    (err, commited, snapshot) ->
      if err
        console.error 'error', err
        return
      console.log 'commited? '+commited
      console.log 'server data', snapshot.val()
    ,
    false
  )

And output:

child_added https://my_firebase.firebaseio.com/items/item1 { my_key: 'my_val' }
transaction on data null
commited? false
server data null

Same happens when third parameter of transaction(...) is true. To make this code work, I have to change ref.once 'child_added', (snapshot) -> to ref.on 'child_added', (snapshot) -> (once to on). After this change output is:

child_added https://my_firebase.firebaseio.com/items/item1 { my_key: 'my_val' }
transaction on data { my_key: 'my_val' }
commited? true
server data { my_key: 'new_val' }

It seems that for some reason when I am using once data are not synced properly and local snapshot is not updated and transaction "thinks" that there is no data under the ref. Is it a bug or I am doing something wrong? I know about transactions that updateFunction can be called more than one time, and about third parameter (I have tried true and false options for it) but still I can't understand why transaction does not work when using once to obtain a child.

user606521
  • 14,486
  • 30
  • 113
  • 204

1 Answers1

5

The transaction should eventually succeed, and run on the correct state of the data, but will initially run in an "uncached" state, meaning it will run against the client's local copy of the data (likely to be null), try to commit the change to the server (which will fail), and then re-try the transaction.

This is normal, and expected. If, however, the transaction does not ever succeed, I would recommend reaching out to the support folks at support@firebase.com to continue troubleshooting the problem.

Rob DiMarco
  • 13,226
  • 1
  • 43
  • 55
  • 1
    This is not normal I think because `once, 'child_added'` returned correct data so I believe it was synced with local copy? Why then transaction operates on null? Anyway this is stupid - imagine that the only thing I want to do in my app is to run a transaction - this means that my app will always fail because data wont be synced and transaction will see `null`. I believe that if data is not synced transaction should check it on server... – user606521 Nov 27 '14 at 22:01
  • 1
    If you're using `once`, the client will not cache any data, because you've indicated that you're only interested in retrieving it *one time*, but not keep it *updated*. If you use `on` instead, the client will always have the data cached and keep that cache updated. – Rob DiMarco Nov 29 '14 at 00:41
  • 1
    But I want to check data only once and then run transaction. I tried to re-run transaction after first one fails, but again data passed to update function are `null`. – user606521 Nov 30 '14 at 10:29
  • 3
    Basically, if you get `null` as input in the transaction function, return it. This will make firebase sdk retry eventually with the updated value. I ran into this, and my mistake was to return `undefined` which cancels the transaction even before the data is fetched from the server. – Ayoub Kaanich Nov 10 '15 at 22:39