パスにデータがある場合でも、Firebaseトランザクションはパスでnullを読み取ります

Dec 22 2020

Firebaseトランザクションがデータをnullとして読み取ることがあることを理解していますが、サーバーから値が取得されてコミットされるまで、ループが再度実行されます。ただし、トランザクションがnullデータを読み取り、nullの場合に返す値をコミットするという独特の状況に直面しています。添付のコードをご覧ください。

 deductTransaction.transaction((current_value) => {
       if (current_value != null) {
           return current_value - cost;
       }
       return 25;
   });

上記のコードでは、「deductTransaction」は更新したいデータ(番号)のパスです

上記のコードは、場合によっては正常に実行されます。つまり、nullが読み取られた場合にループが再度実行され、場合によっては1回だけ実行され、そのパスにデータがあったとしても値をnullとして読み取り、25をコミットして元のデータを破棄します。

PS:私は髪を抜くところですので、どんな助けでも大歓迎です

回答

1 FrankvanPuffelen Dec 22 2020 at 20:48

ある場所でトランザクションを実行すると、その場所の値のクライアントの現在の推測を使用して、コールバック/ハンドラーがすぐに呼び出されます。ほとんどの場合、現在の値のこの最初の推測はですnull

ハンドラーはこの状況を処理する必要があります。つまり、その場所にデータが存在せず、コストを差し引きたいとすると、どうなるでしょうか。通常は、戻る-25か、トランザクションを中止するように指示します。

どちらの方法でも、初期推定値と新しい値がデータベースサーバーに送信され、データベースサーバーは初期推定値が間違っていたことを検出し、現在の値を呼び出し元に返します。次に、SDKはハンドラー/コールバックを再度呼び出し、現在の値を(うまくいけば正しい)推測します。

参照:

  • Firebaseリアルタイムデータベーストランザクションハンドラーは、ほとんどの場合2回呼び出されます(上記のフローの図を使用)
  • FirebaserunTransactionが機能しない-MutableDataがnull
  • Firebaseでの競合解決を理解する
  • FirebaseトランザクションのcurrentDataが常にnilになるのはなぜですか?

注:最近では、increment演算子を使用して、トランザクションなしでインクリメントおよびデクリメント操作を実行できます。これにより、コードが大幅に簡素化され、Firebase Realtime Databaseの値をアトミックにインクリメントする速度をどのくらい速くできるかを示すように、パフォーマンスが向上します。。

比較のために:incrementオペレーターは、0その場所に値が存在しない場合の現在の値を想定します。