代码之家  ›  专栏  ›  技术社区  ›  Lance Samaria

如何触发TransactionResult.abort()如果ref不再存在

  •  0
  • Lance Samaria  · 技术社区  · 4 年前

    如果我想从数据库中检索一些数据,我可以使用 snapshot.exists() :

    ref.observeSingleEvent(of: .value, with: { (snapshot) in
    
        if !snapshot.exists() { return }
    }
    

    Transaction ,我只是更新了一些不再存在的东西,它没有得到一个错误,而是更新了ref,这是我没想到的。

    @posts
      @postId_123 // this post has actually been deleted
         -url: ...
         -timeStamp: ...
         -comments_count: 10
    

    -2用户可以删除其中一条评论,而不必实际查看。一旦发生这种情况 评论\u计数 会减少。

    let postsRef = Database.database().reference().child("posts").child("postId_123").child("comments_count")
    postsRef.runTransactionBlock({ (mutableData: MutableData) -> TransactionResult in
            
        var currentCount = mutableData.value as? Int ?? 0
    
        mutableData.value = currentCount - 1
        currentCount = mutableData.value as? Int ?? 0
            
        if currentCount < 0 {
            mutableData.value = 0
        }
            
        return TransactionResult.success(withValue: mutableData)
            
    }, andCompletionBlock: { [weak self](error, completion, snap) in
        if !completion || (error != nil) {
            print("The value wasn't able to update")
            print(error?.localizedDescription as Any)
                
        } else {
            print("The value updated")
        }
    })
    

    邮政编码:123 在事务运行之前被删除,上述事务将导致 邮政编码:123 放回柱子里面参考:

    @posts
      @postId_123 // this postId has been been put back but should no longer exist
         -comments_count: 0
    

    TransactionResult.abort() 如果mutableData的子级不再存在?

    let postsRef = Database.database().reference().child("posts").child("postId_123").child("comments_count")
    postsRef.runTransactionBlock({ (mutableData: MutableData) -> TransactionResult in
    
        if !mutableData.exists() { // *** this check isn't real and is used just as an example ***
    
            return TransactionResult.abort() // this is real
        }
    
        var currentCount = mutableData.value as? Int ?? 0
    
        // ...
     })
    
    0 回复  |  直到 4 年前
        1
  •  0
  •   Lance Samaria    4 年前

    这是我找到的唯一触发中止的方法。如果有人以其他方式发帖,我会删除这个答案。

    首先要知道的是,对于这个答案,无论你要管理的是哪个孩子 Transaction 上必须有一个 价值 事先不能 . 例如,如果尝试运行 交易 评论\u计数 邮递 0 (目前尚无评论)。 评论\u计数 永远不会更新 :

    var dict = [String: Any]()
    dict.updateValue(postId_123, forKey: "postId")
    dict.updateValue(0, forKey: "comments_count") // *** this is important ***
    dict...
    
    let postsRef = ...child("posts").child(postId_123)
    postsRef.updateChildValues(dict)
    

    交易 评论\u计数 ,如果值为 然后这个帖子被删除了(这是假设没有其他方法可以删除) 评论\u计数 那就跑吧 TransactionResult.abort() . 内部 completionBlock 你去看看 error

    let postsRef = Database.database().reference().child("posts").child("postId_123").child("comments_count")
    postsRef.runTransactionBlock({ (mutableData: MutableData) -> TransactionResult in
    
        // if nil then the post was deleted
        let checkIfCountExists = mutableData.value as? Int
        if checkIfCountExists == nil {
                    
            return TransactionResult.abort()
        }
    
        // not nil then continue on
        var currentCount = mutableData.value as? Int ?? 0
    
        mutableData.value = currentCount - 1
        currentCount = mutableData.value as? Int ?? 0
            
        if currentCount < 0 {
            mutableData.value = 0
        }
            
        return TransactionResult.success(withValue: mutableData)
            
    }, andCompletionBlock: { [weak self](error, completion, snap) in
    
        if !completion || (error != nil) {
            print("The value wasn't able to update")
            print(error?.localizedDescription as Any)
    
            if error == nil {
                print("*** transaction value is nil ***")
                return
            }
    
            // there is a value there but something else went wrong so try again
    
        } else {
            print("The value updated")
        }
    })