Firebase交易后来多次回来?

时间:2016-04-22 21:56:21

标签: javascript firebase firebase-realtime-database

这是一件相当奇怪的事情,很难再现。不是错误报告的最佳状态,我道歉。

我使用.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);

我有效地使用Firebase交易作为一种互斥锁:

  • 通过交易将值存储在某个位置。

  • 设置该位置的onDisconnect,以便在我的应用程序在工作时死亡时删除该值。

  • 做一些事情。

  • 删除该位置的onDisconnect,因为我已经完成了这些工作。

  • 删除该位置的值。

我每隔几分钟就做一次,这一切都很棒。事情得到了完美的编写和删除,日志显示我创建锁定,执行操作,然后释放锁定。

奇怪的部分是小时之后发生的事情。偶尔Firebase有维护,我的应用程序获得了一堆权限被拒绝的错误。在这种情况发生的同时,我突然开始在日志中获得一堆这样的输出:

Attempting update 1
Attempting update 2
Attempting update 3

......换句话说,看起来交易从未完全完成,并且他们现在正在尝试重试该位置无法再读取。它几乎就像在事务()代码中的闭包从未完成,并且由于某种原因它现在被重新执行。

我是否遗漏了一些关于如何结束交易的重要内容?

(注意:我最初将此帖子发布到Firebase Google Group,但最终提醒代码问题应该转到Stack Overflow。我为交叉发布道歉。)

1 个答案:

答案 0 :(得分:0)

只是一个猜测,但我想知道当您的应用从Firebase获得权限拒绝错误时,是否使用updateFunc()调用了您的null功能。 (如果是这样,我可以相信这是他们“离线写作”支持的一部分。)

在任何情况下,您都应该将null作为可能的状态处理。 Saving Transactional Data说:

  

transaction()将被多次调用,并且必须能够处理   null数据。即使数据库中存在现有数据,也可能没有   在运行事务函数时本地缓存。

我不知道Firebase的交易机制的复杂性,但我会尝试更改您的.set(null)以将值设置为0,而是更改您的.remove()以设置值使用.set(0),并将updateFunc()中的行更改为:

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

不幸的是,这假设'/path/to/location'最初在某个时候设置为0。如果这是一个问题,也许你可以使用nullundefined混在一起。例如,如果Firebase使用其中一个用于不存在的数据而另一个用于脱机数据,则会很好。