2016-04-22 88 views
1

這是一件相當奇怪的事情,很難重現。不是錯誤報告的最佳狀態,我很抱歉。Firebase交易多次回來多次?

我正在使用.transaction()將值寫入Firebase中的某個位置。下面是一些僞代碼:

var ref = firebase.child('/path/to/location'); 

var storeSafely = function(val) { 
    ref.transaction(
    function updateFunc(currentData) { 
     console.log('Attempting update: ' + JSON.stringify(val)); 

     if (currentData) return; 

     return val; 
    }, 
    function onTransactionCompleteFunc(err, isCommitted, snap) { 
     if (err) { 
     console.log('Error in onTransactionCompleteFunc: ' + JSON.stringify(err)); 
     return; 
     } 

     if (! isCommitted) { 
     console.log('Not committed'); 
     return; 
     } 

     ref.onDisconnect().remove(); 
     doSomeStuff(); 
    }); 
}; 

var doSomeStuff = function() { 
    // Things get done, time passes. 

    console.log('Cleaning up'); 
    ref.onDisconnect().cancel(); 
    ref.set(
    null, 
    function onSetCompleteFunc(err) { 
     if (err) { 
     console.log('Error in onSetCompleteFunc: ' + JSON.stringify(err)); 
     } 
    }); 
}; 

storeSafely(1); 
// later... 
storeSafely(2); 
// even later... 
storeSafely(3); 

我有效利用火力地堡交易作爲一種互斥鎖:

  • 商店在通過事務的地址的值。

  • 將onDisconnect設置爲刪除值,以防我的應用在工作時死亡。

  • 做一些事情。

  • 刪除該位置的onDisconnect,因爲我完成了這些東西。

  • 刪除該位置的值。

我每隔幾分鐘就會做一次,這一切都很好。事情會被完美地寫出來,並且日誌會顯示我創建鎖,執行任務,然後釋放鎖。

奇怪的部分是什麼發生了小時以後。有時Firebase會進行維護,並且我的應用會獲得一堆被拒絕的權限錯誤。同時出現這種情況,我突然開始變得一堆此輸出的日誌:

Attempting update 1 
Attempting update 2 
Attempting update 3 

...換句話說,它看起來像交易從未完全完成,他們正試圖重試現在無法再讀取該位置了。這幾乎就像transaction()代碼中沒有完成的閉包,並且由於某種原因它現在被重新執行。

我在這裏錯過了一些關於如何結束交易真正重要的東西嗎?

(注:我最初發布這個到火力地堡谷歌集團,但最終被提醒的是代碼的問題都應該去堆棧溢出我的交叉發表道歉)

回答

0

只是一個猜測,但是我想知道當您的應用從Firebase獲取權限被拒絕的錯誤時,您的updateFunc()函數是否正在調用null。 (如果是這樣,我可以認爲這是他們的「離線寫入」支持的一部分。)

無論如何,您應該處理null作爲可能的狀態。 Saving Transactional Data說:

transaction()將被多次調用,並且必須能夠處理 null數據。即使數據庫中有現有數據,在事務功能運行時,也不會在本地緩存 。

不知火力地堡的交易mechansim的複雜性,但我會試着改變你的.set(null)設定值0而是改變你的.remove()也設定值與.set(0),並更改行updateFunc()於:

if (currentData === null || currentData) return; 

不幸的是,假設'/path/to/location'在一些點初始設置爲0。如果這是一個問題,也許你可以用nullundefined混合。例如,如果Firebase將其中一個用於不存在的數據,而另一個用於脫機狀態,則會很好。