Reputation: 3705
I'm trying to use async/await with transaction. But getting error "Argument "updateFunction" is not a valid function."
var docRef = admin.firestore().collection("docs").doc(docId);
let transaction = admin.firestore().runTransaction();
let doc = await transaction.get(docRef);
if (!doc.exists) {throw ("doc not found");}
var newLikes = doc.data().likes + 1;
await transaction.update(docRef, { likes: newLikes });
Upvotes: 13
Views: 13225
Reputation: 937
IMPORTANT: As noted by a couple of the users, this solution doesn't use the transaction properly. It just gets the doc using a transaction, but the update runs outside of it.
Check alsky's answer. https://stackoverflow.com/a/52452831/683157
Take a look to the documentation, runTransaction must receive the updateFunction function as parameter. (https://firebase.google.com/docs/reference/js/firebase.firestore.Firestore#runTransaction)
Try this
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 });
Upvotes: 4
Reputation: 23271
If you look at the docs you see that the function passed to runTransaction
is a function returning a promise (the result of transaction.get().then()
). Since an async function is just a function returning a promise you might as well write db.runTransaction(async transaction => {})
You only need to return something from this function if you want to pass data out of the transaction. For example if you only perform updates you won't return anything. Also note that the update function returns the transaction itself so you can chain them:
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}`);
}
Upvotes: 7
Reputation: 3861
In my case, the only way I could get to run my transaction was:
const firestore = admin.firestore();
const txRes = await firestore.runTransaction(async (tx) => {
const docRef = await tx.get( firestore.collection('posts').doc( context.params.postId ) );
if(!docRef.exists) {
throw new Error('Error - onWrite: docRef does not exist');
}
const totalComments = docRef.data().comments + 1;
return tx.update(docRef.ref, { comments: totalComments }, {});
});
I needed to add my 'collection().doc()' to tx.get directly and when calling tx.update, I needed to apply 'docRef.ref', without '.ref' was not working...
Upvotes: 1
Reputation: 325
The above did not work for me and resulted in this error: "[Error: Every document read in a transaction must also be written.]".
The below code makes use of async/await and works fine.
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);
}
Upvotes: 25