2013-05-03 19 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