2013-05-03 18 views
11

當我使用transaction()更新的位置,在該位置的數據是返回null即使有位置的一些數據。火力地堡交易API調用當前數據爲空

我試過transaction()在讀取數據之後,它在同一位置給出了該位置的所有數據。

如果情況與上述情況類似,我如何使用transaction()

回答

20

事務以Amazon SimpleDB或分片數據庫集羣的方式工作。也就是說,它們「最終一致」,而不是保證一致。

因此,當您使用事務時,處理函數可能會使用本地值(在某些情況下爲空,如果它從未檢索過)再次與同步值(服務器上的任何值)一起被調用。

例子:

pathRef.transaction(function(curValue) { 

    // this part is eventually consistent and may be called several times 

}, function(error, committed, ss) { 

    // this part is guaranteed consistent and will match the final value set 

}); 

這是真的,你必須反正接近交易的心態。您應該始終期待多次通話,因爲第一筆交易可能會與另一次更改發生衝突並被拒絕。您不能使用事務的處理方法來獲取服務器值(儘管您可以從成功回調中讀取它)。

防止本地觸發事件

當交易發生時,它達到了延遲補償服務器之前被觸發本地事件。如果事務失敗,則本地事件將被恢復(觸發更改或刪除事件)。

您可以使用applyLocally屬性on transactions來覆蓋此行爲,這會使本地結果變慢但確保只在本地觸發服務器值。

pathRef.transaction(function(curValue) { 

    // this is still called multiple times 

}, function(error, committed, ss) { 

    // this part is guaranteed consistent and will match the final value set 

}, 
    // by providing a third argument of `true`, no local event 
    // is generated with the locally cached value. 
true); 
+0

謝謝,我插入數據後將近3天使用了事務。所以你說要先使用事務,我們需要檢查該位置是否存在任何值。 – Ashok 2013-05-06 06:28:33

+0

「最終持久性」與它在服務器上的長度無關,只是它在客戶端上的長度 - 在您要求它之前它不在客戶端上。你不一定需要檢查一個值是否存在,只要接受該函數可能被多次調用,並且最終會被服務器值調用。 – Kato 2013-05-06 13:52:11

+0

@Kato我認爲這個交易對於Node服務器用來減少用戶餘額是一件壞事?就好像另一個節點服務器預先寫入了一樣,那麼我希望它寫入相同的東西(所以設置會更好?) – 2016-05-17 22:14:16

7

你需要遵循這個模式:

var pinRef = firebase.database().ref('vm-pin-generator'); 
pinRef.transaction(function(oldPin) { 
    // Check if the result is NOT NULL: 
    if (oldPin != null) { 
     return localPinIncrementor(oldPin); 
    } else { 
     // Return a value that is totally different 
     // from what is saved on the server at this address: 
     return 0; 
    } 
}, function(error, committed, snapshot) { 
    if (error) { 
     console.log("error in transaction"); 
    } else if (!committed) { 
     console.log("transaction not committed"); 
    } else { 
     console.log("Transaction Committed"); 
    } 
}, true); 

火力地堡通常在檢索首次一鍵返回空值,但同時節省檢驗該新值類似於舊的價值或不。如果沒有,firebase將再次運行整個過程,這次服務器返回正確的值。

添加null檢查,並返回一個完全意想不到的值(0在這種情況下)將火力再次運行週期。

+1

這應該是正確的答案。 – martinjbaker 2016-10-22 14:12:32

+0

而不是返回0,您可以返回undefined以中止事務。 「如果返回undefined(即你沒有參數返回),事務將被中止,並且這個位置的數據不會被修改。」 https://firebase.google.com/docs/reference/admin/node/admin.database.Reference#transaction – 2017-01-08 16:49:05

+0

我不知道Firebase中是否發生了一些變化,因爲這個答案已經寫好,但是如果我返回undefined或者什麼也沒有,Firebase將掛起60秒,然後超時。我想最終的結果是一樣的,但這似乎不是一件好事。 – 2017-05-25 14:58:41