2016-04-22 89 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将其中一个用于不存在的数据,而另一个用于脱机状态,则会很好。