Les transactions Firebase dans NodeJS sont toujours exécutées 3 fois?

Chaque fois que je définis une transaction Firebase dans NodeJS, je remarque qu’elle est toujours exécutée trois fois – les deux premières fois avec des données nulles, puis enfin une troisième fois avec des données réelles. Est-ce normal / prévu?

Par exemple ce code:

firebaseOOO.child('ref').transaction(function(data) { console.log(data); return data; }); 

génère les éléments suivants:

 null null i1: { a1: true } 

Je me serais attendu à ce qu’il imprime seulement le dernier article.

Pour répondre à une question dans les commentaires, voici la même chose avec un rappel:

 firebaseOOO.child('ref').transaction(function(data) { console.log(data); return data; }, function(error, committed, snapshot) { if (error) console.log('failed'); else if (!committed) console.log('aborted'); else console.log('committed'); console.log('fin'); }); 

Ce qui donne la sortie suivante:

 null null i1: { a1: true } committed fin 

J’avais lu les détails du fonctionnement des transactions avant de poster la question. J’avais donc essayé de définir applyLocally sur false comme ceci:

 firebaseOOO.child('ref').transaction(function(data) { console.log('hit'); return data; }, function(){}, false); 

Mais il frappe encore 3 fois (juste une double vérification) alors j’ai pensé que c’était quelque chose de différent. Obtenir la “valeur” avant d’effectuer une transaction “fonctionne” comme prévu, dans la mesure où il ne frappe qu’une seule fois, et cela indépendamment de ce qui est appliqué à applyLocally, donc je ne suis pas sûr de ce que applyLocally fait? Voici ce que je veux dire par obtenir la valeur avant d’effectuer une transaction:

 firebaseOOO.child('ref').once('value', function(data) { console.log('1'); firebaseOOO.child('ref').transaction(function(data) { console.log('2'); return data; }); }); 

Les sorties:

 1 2 

@ Michael: Comment peut-on utiliser ce comportement? Les transactions servent principalement à ce que les données s’utilisent elles-mêmes pour se modifier – l’incrément prototype ++. Donc, si j’ai besoin d’append 1 à la valeur existante de 10 et de continuer à travailler avec le résultat de 11, les deux premières fois que la fonction frappe, j’aurai un résultat erroné de 1 que je dois gérer, et enfin le résultat correct de 11 sur le troisième coup. Comment puis-je utiliser ces deux 1 initiaux? Un autre scénario (et peut-être que je ne devrais pas utiliser de transactions pour cela, mais si cela a fonctionné comme je le pensais, c’est un code plus propre) consiste à insérer une valeur si elle n’existe pas encore. Si les transactions n’interviennent qu’une seule fois, une valeur NULL signifierait que la valeur n’existe pas. Vous pouvez donc, par exemple, initialiser le compteur à 1 dans ce cas, sinon append 1 à la valeur. Avec les Null Null, ce n’est pas possible.

Il semblerait que tout ce qu’il faut retenir est simplement d’utiliser le motif «une fois» plus souvent qu’autrement.

MOTIF DE TRANSACTION UNE FOIS:

 firebaseOOO.child('ref').once('value', function(data) { console.log('1'); firebaseOOO.child('ref').transaction(function(data) { console.log('2'); return data; }); }); 

Le comportement que vous voyez ici est lié à la manière dont Firebase déclenche les événements locaux, puis se synchronise avec les serveurs Firebase. Dans cet exemple spécifique, “l’exécution à trois resockets” ne se produira que la toute première fois que vous exécutez le code. Après cela, l’état est complètement synchronisé et il ne se déclenche qu’une fois. Ce comportement est détaillé ici: https://www.firebase.com/docs/transactions.html (voir la section “Lorsqu’une transaction est exécutée, les événements suivants se produisent”.)

Si, par exemple, vous avez un on () en attente au même endroit puis, ultérieurement, exécutez le même code de transaction, vous verrez qu’il ne sera exécuté qu’une fois. En effet, tout est synchronisé avant l’exécution de la transaction (dans le cas idéal; sauf en cas de conflit normal, etc.).

transaction () sera appelé plusieurs fois et doit pouvoir traiter des données nulles. Même s’il existe des données dans votre firebase database, elles ne peuvent pas être mises en cache localement lors de l’exécution de la fonction de transaction.

 firebaseOOO.child('ref').transaction(function(data) { if(data!=null){ console.log(data); return data; } else { return data; } }, function(error, committed, snapshot) { if (error) console.log('failed'); else if (!committed) console.log('aborted'); else console.log('committed'); console.log('fin'); });