【问题标题】:What is the proper way to use transactions in firebase with Angular使用 Angular 在 Firebase 中使用事务的正确方法是什么
【发布时间】:2018-11-28 04:07:33
【问题描述】:

在使用 Firebase 时,我通常使用 AngularFire2。但是这次我没有,我使用了普通的 Firebase 库,因为当我检查 AngularFire2 上的文档以了解我需要的事务的使用情况时,我没有找到它。

使用普通的 Firebase 库时,我遇到了这个错误,表示事务未提交,但数据仍保存到 Firebase。 谁能指出我犯的错误?

这是我的代码:

saveSeats(key, numbers){
  for (let i = 0; i < numbers.length; i++) {
    const num = numbers[i].toString();
    const objPath = `${this.basePath}/${key}/${num}`;      
    const busesRef = firebase.database().ref("buses/"+key+"/"+num); 

    busesRef.transaction(function(currentValue) {
      if (currentValue === null) {
        let newRow = JSON.stringify({ number: num, status: "reserved", timestamp: Date.now() });
        busesRef.child("0").set(newRow);
      } else {
        console.log('Value Already Exists');
      }    
    }, function(error, committed, snapshot) {
      if (error) {
        console.log('Transaction failed abnormally!', error);
      }else if (!committed) {
        console.log('We aborted the transaction (because number already exists).');
      } else {
        console.log('Number added!');
      }
      console.log("Number: ", snapshot.val());      
    });

  }

}

【问题讨论】:

    标签: angular firebase firebase-realtime-database angularfire2 angular7


    【解决方案1】:

    您不应在事务中使用set() 方法,如doc 中所述:

    注意:使用 set() 修改数据将取消任何待处理的事务 在那个位置,所以如果混合 set() 和 transaction() 来更新相同的数据。

    您应该“传递transaction() 一个更新函数,用于将当前值转换为新值。”

    所以以下应该正常工作:

      busesRef.transaction(function(currentValue) {
        if (currentValue === null) {
          let newRow = JSON.stringify({ number: num, status: "reserved", timestamp: Date.now() });
          return newRow;  // <- Here the function returns the new value
        } else {
          console.log('Value Already Exists');
          return; // Will abort the transaction.
        }    
      },
      ....
    

    最后,我认为您不需要对对象进行字符串化。执行以下操作应该可以:

          let newRow = { number: num, status: "reserved", timestamp: Date.now() };
          return newRow;
    

    或者,当然,只是

          return { number: num, status: "reserved", timestamp: Date.now() };
    

    进一步考虑:

    我注意到您将事务包装在 for 循环中,这意味着您将修改不同 busesRef 节点的值。你不应该在一个交易中完成所有这些修改吗?而不是一组“原子”事务,每个事务都会修改给定busesRef 节点的值?这取决于您的具体用例。

    【讨论】:

    • 这让我明白了很多。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多