2016-04-22 13 views
1

これはかなり奇妙なことであり、再現するのは難しいです。バグ報告の最善の状態ではない、私はお詫び申し上げます。Firebaseトランザクションは何度も何度も戻ってきますか?

Firebaseの場所に値を書き込むために.transaction()を使用しています。ここではいくつかの擬似コードは次のとおりです。

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 

...つまり、それが完全に完了しません取引のように見える、と彼らは再試行しようとしていますこれ以上場所を読み取ることができなくなりました。これは決して完了しなかったtransaction()コードのクロージャーとほぼ同じです。何らかの理由で今すぐ再実行されています。

トランザクションを終了する方法についてここで本当に重要なことがありませんか?

(注意:私はもともとFirebase Googleグループへの投稿ですが、最終的にそのコードの質問はスタックオーバーフローに行くことになっている思い出した私は、クロスポストをお詫び申し上げます)

答えて

0

だけの推測あなたのupdateFunc()関数がnullで呼び出されているかどうかは、あなたのアプリがFirebaseからの許可拒否エラーを受け取ったときには不思議です。もしそうなら、私はそれが「オフライン書き込み」サポートの一部だと信じることができます。

いずれの場合も、可能な状態としてnullを処理する必要があります。 Saving Transactional Dataは言う:

transaction()は複数回呼び出され、 nullデータを扱うことができなければなりません。データベースに既存のデータがある場合でも、トランザクション機能の実行時に がローカルにキャッシュされないことがあります。

私はFirebaseのトランザクションmechansimの複雑さを知らないが、私はあなたの.remove().set(0)で値を設定し、updateFunc()であなたの行を変更するように変更、代わりに0に値を設定するために、あなたの.set(null)を変更しようとするだろうTo:

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

残念ながら、それは'/path/to/location'が最初にいくつかの点で0に設定されていることを前提としています。それが問題ならば、おそらくnullundefinedの間でうんざりすることができます。たとえば、存在しないデータに対してFirebaseが1つを使用し、オフラインで別のデータを使用した場合、Firebaseがうまくいくでしょう。