Solución:
Lo anterior no funcionó para mí y resultó en este error: “[Error: Every document read in a transaction must also be written.]”.
El siguiente código hace uso de async / await y funciona bien.
try{
await db.runTransaction(async transaction => {
const doc = await transaction.get(ref);
if(!doc.exists){
throw "Document does not exist";
}
const newCount = doc.data().count + 1;
transaction.update(ref, {
count: newCount,
});
})
} catch(e){
console.log('transaction failed', e);
}
IMPORTANTE: Como señalaron un par de usuarios, esta solución no usa la transacción correctamente. Es solo obtiene el documento mediante una transacción, pero la actualización se ejecuta fuera de ella.
Comprueba la respuesta de Alsky. https://stackoverflow.com/a/52452831/683157
Eche un vistazo a la documentación, runTransaction debe recibir la función updateFunction como parámetro. (https://firebase.google.com/docs/reference/js/firebase.firestore.Firestore#runTransaction)
Prueba esto
var docRef = admin.firestore().collection("docs").doc(docId);
let doc = await admin.firestore().runTransaction(t => t.get(docRef));
if (!doc.exists) {throw ("doc not found");}
var newLikes = doc.data().likes + 1;
await doc.ref.update({ likes: newLikes });
Si miras los documentos, ves que la función pasó a runTransaction
es una función que devuelve una promesa (el resultado de transaction.get().then()
). Dado que una función asíncrona es solo una función que devuelve una promesa, también puede escribir db.runTransaction(async transaction => {})
Solo necesita devolver algo de esta función si desea transferir datos de la transacción. Por ejemplo, si solo realiza actualizaciones, no devolverá nada. También tenga en cuenta que la función de actualización devuelve la transacción en sí para que pueda encadenarlos:
try {
await db.runTransaction(async transaction => {
transaction
.update(
db.collection("col1").doc(id1),
dataFor1
)
.update(
db.collection("col2").doc(id2),
dataFor2
);
});
} catch (err) {
throw new Error(`Failed transaction: ${err.message}`);
}