FIRDatabaseReference observe获取空更新,而另一个引用正在运行事务

时间:2017-07-14 06:28:14

标签: firebase firebase-realtime-database rx-swift

我们将Firebase DB与RxSwift一起使用,并且遇到了交易问题。我不认为它们与RxSwift的组合有关,但这是我们的背景。

我在Firebase DB中观察数据是否有任何值更改:

let child = dbReference.child(uniqueId)
let dbObserverHandle = child.observe(.value, with: { snapshot -> () in
    guard snapshot.exists() else {
        log.error("empty snapshot - child not found in database")
        observer.onError(FirebaseDatabaseConsumerError(type: .notFound))
        return
    }

    //more checks
    ...

    //read the data into our object
    ...

    //finally send the object as Rx event
    observer.onNext(parsedObject)
}, withCancel: { _ in
    log.error("could not read from database")
    observer.onError(FirebaseDatabaseConsumerError(type: .databaseFailure))
})

单独没有问题。读取并观察数据没有任何问题。数据的变化按原样传播。

只要应用程序的另一部分修改了具有事务的观察者数据,就会出现问题:

dbReference.runTransactionBlock({ (currentData: FIRMutableData) -> FIRTransactionResult in
    log.debug("begin transaction to modify the observed data")

    guard var ourData = currentData.value as? [String : AnyObject] else {
        //seems to be nil data because data is not available yet, retry as stated in the transaction example https://firebase.google.com/docs/database/ios/read-and-write
        return TransactionResult.success(withValue: currentData)
    }
    ...            
    //read and modify data during the transaction
    ...

    log.debug("complete transaction")

    return FIRTransactionResult.success(withValue: currentData)
}) { error, committed, _ in
    if committed {
        log.debug("transaction commited")
        observer(.completed)
    } else {
        let error = error ?? FirebaseDatabaseConsumerError(type: .databaseFailure)
        log.error("transaction failed - \(error)")
        observer(.error(error))
    }
}

事务在第一次尝试时收到nil数据(这是你应该能够处理的事情。我们只是打电话 return TransactionResult.success(withValue: currentData) 在这种情况下。 但这会传播给上述观察者。观察者遇到“空快照 - 在数据库中找不到子”的情况,因为它收到一个空快照。

再次运行事务,更新数据并成功提交。并且观察者接收到更新数据的另一个更新,一切都很好。

我的问题: 有没有更好的方法来处理事务期间的nil-data而不是使用FIRTransactionResult.success将其写入数据库? 这似乎是完成此事务运行并触发重新运行新数据的唯一方法,但也许我遗漏了一些东西 - 为什么我们收到空的currentData?数据显然是存在的,因为它被观察到了。 如果事务触发对该数据的所有观察者的“临时删除”,则该事务似乎无法使用该行为。

更新

放弃并重组数据以摆脱使用交易的必要性。通过不同的数据结构,我们能够同时更新数据集,而不会有数据损坏的风险。

0 个答案:

没有答案