2013-05-03 2 views
11

Quand j'utilise transaction() mettre à jour un emplacement, les données à cet endroit est retour nulle, même si l'emplacement ayant des données.transaction Firebase api appel données en cours est nul

J'ai essayé transaction()après avoir lu les données au même endroit où il donne toutes les données à cet endroit.

Comment puis-je utiliser transaction() si le cas est comme ci-dessus?

Répondre

20

Les transactions fonctionnent à la manière de SimpleDB d'Amazon ou d'un cluster de base de données fragmenté. C'est-à-dire qu'ils sont "finalement cohérents" plutôt que garantis cohérents. Ainsi, lorsque vous utilisez des transactions, la fonction de traitement peut être appelée plusieurs fois avec une valeur locale (dans certains cas nulle si elle n'a jamais été récupérée) et de nouveau avec la valeur synchronisée (tout ce qui est sur le serveur).

Exemple:

pathRef.transaction(function(curValue) { 

    // this part is eventually consistent and may be called several times 

}, function(error, committed, ss) { 

    // this part is guaranteed consistent and will match the final value set 

}); 

C'est vraiment l'état d'esprit avec lequel vous devez aborder la transaction de toute façon. Vous devez toujours attendre plusieurs appels, car la première transaction peut entrer en conflit avec une autre modification et être rejetée. Vous ne pouvez pas utiliser la méthode de traitement d'une transaction pour extraire la valeur du serveur (bien que vous puissiez la lire hors du rappel de succès).

empêcher l'événement déclenché localement

Lorsque la transaction se produit, un événement local est déclenché avant d'atteindre le serveur de compensation de la latence. Si la transaction échoue, l'événement local sera annulé (un événement de modification ou de suppression est déclenché).

Vous pouvez utiliser la propriété applyLocallyon transactions pour remplacer ce comportement, ce qui rend les résultats locaux plus lents mais garantit que seule la valeur du serveur est déclenchée localement.

pathRef.transaction(function(curValue) { 

    // this is still called multiple times 

}, function(error, committed, ss) { 

    // this part is guaranteed consistent and will match the final value set 

}, 
    // by providing a third argument of `true`, no local event 
    // is generated with the locally cached value. 
true); 
+0

Merci, j'ai utilisé la transaction presque 3 jours après l'insertion des données. Donc, vous dites d'utiliser la transaction d'abord, nous devons vérifier cet emplacement si une valeur existe ou non? – Ashok

+0

"Éventuellement persistant" n'a rien à voir avec la longueur sur le serveur, juste la longueur qu'il a été sur le client - ce n'est pas sur le client jusqu'à ce que vous le demandiez. Vous n'avez pas forcément besoin de vérifier qu'une valeur existe, acceptez simplement que la fonction peut être appelée plusieurs fois et sera "éventuellement" appelée avec la valeur du serveur. – Kato

+0

@Kato Je suppose que cette transaction serait une mauvaise chose pour un serveur Node à utiliser pour décrémenter le solde d'un utilisateur?Comme si un autre serveur de noeud faisait une écriture à l'avance, alors je veux qu'il écrive la même chose (ainsi set serait mieux?) –

7

Vous devez suivre ce modèle:

var pinRef = firebase.database().ref('vm-pin-generator'); 
pinRef.transaction(function(oldPin) { 
    // Check if the result is NOT NULL: 
    if (oldPin != null) { 
     return localPinIncrementor(oldPin); 
    } else { 
     // Return a value that is totally different 
     // from what is saved on the server at this address: 
     return 0; 
    } 
}, function(error, committed, snapshot) { 
    if (error) { 
     console.log("error in transaction"); 
    } else if (!committed) { 
     console.log("transaction not committed"); 
    } else { 
     console.log("Transaction Committed"); 
    } 
}, true); 

Firebase retourne habituellement une valeur null lors de la récupération d'une clé pour la première fois, mais tout en économisant, il vérifie si la nouvelle valeur est similaire à la valeur plus ou ne pas. Si ce n'est pas le cas, Firebase réexécutera le processus entier, et cette fois la valeur correcte est retournée par le serveur.

L'ajout d'un null vérifier et renvoyer une valeur totalement inattendue (0 dans ce cas) fera de nouveau exécuter le cycle par Firebase.

+1

cela devrait être la bonne réponse. – martinjbaker

+0

Au lieu de renvoyer 0, vous pouvez renvoyer undefined pour annuler la transaction. "Si undefined est retourné (c'est-à-dire que vous revenez sans arguments), la transaction sera annulée et les données à cet emplacement ne seront pas modifiées." https://firebase.google.com/docs/reference/admin/node/admin.database.Reference#transaction –

+0

Je ne sais pas si quelque chose a changé dans Firebase depuis que cette réponse a été écrite, mais si je retourne undefined ou rien , Firebase se bloque pendant 60 secondes puis expire. Je suppose que le résultat net est le même, mais cela ne semble pas être une bonne chose à faire. –

Questions connexes