Firebase事务api调用当前数据为空

Ash*_*hok 19 firebase firebase-security

当我transaction()用来更新位置时,即使该位置有一些数据,该位置的数据也会返回null.

我在同一个位置transaction() 读取数据之后尝试了它在该位置提供所有数据的时间.

transaction()如果案件如上所述,我该如何使用?

Kat*_*ato 27

事务以Amazon SimpleDB或分片数据库集的方式工作.也就是说,它们"最终是一致的"而不是保证一致.

因此,当您使用事务时,处理函数可能会被多次调用一个本地值(在某些情况下,如果它从未被检索过,则为null),然后再次使用同步值(服务器上的任何内容).

例:

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

});
Run Code Online (Sandbox Code Playgroud)

这实际上是您必须处理交易的心态.您应该始终期望多次调用,因为第一个事务可能会与另一个更改发生冲突并被拒绝.您不能使用事务的处理方法来获取服务器值(尽管您可以从成功回调中读取它).

防止本地触发的事件

当事务发生时,本地事件在到达服务器之前被触发以进行延迟补偿.如果事务失败,则将还原本地事件(触发更改或删除事件).

您可以在事务上使用该applyLocally属性来覆盖此行为,这会使本地结果变慢但确保仅在本地触发服务器值.

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);
Run Code Online (Sandbox Code Playgroud)


小智 16

你需要遵循这种模式:

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);
Run Code Online (Sandbox Code Playgroud)

Firebase通常在第一次检索密钥时返回空值,但在保存时检查新值是否与旧值相似.如果没有,firebase将再次运行整个过程,这次服务器返回正确的值.

添加一个null检查并返回一个完全意外的值(0在这种情况下)将使firebase再次运行该循环.