I am trying to learn to work with firestore transactions.
Here is my code:
const handleSubmit = (e) => {
e.preventDefault();
console.log(message);
let mergedId = loggedUserId + toBeContactedUserId;
let loggedUserRef = db.collection('users').doc(loggedUserId);
let toBeContactedUserRef = db.collection('users').doc(toBeContactedUserId);
let messageDbRef = db.collection('messages').doc();
db.runTransaction((transaction) => {
transaction.get(loggedUserRef) //First transaction
.then(userDoc => {
let userData = {
...userDoc.data(),
contacts: {
...userDoc.data().contacts,
[toBeContactedUserId]: {
...userDoc.data().contacts[toBeContactedUserId],
lastMsg: message,
unreadMsg: 0
}
}
}
loggedUserRef.set(userData);
})
transaction.get(toBeContactedUserRef) //Second transaction
.then(userDoc => {
let unreadMsgInc = userDoc.data().contacts[loggedUserId].unreadMsg + 1;
let userData = {
...userDoc.data(),
contacts: {
...userDoc.data().contacts,
[loggedUserId]: {
...userDoc.data().contacts[loggedUserId],
lastMsg: message,
unreadMsg: unreadMsgInc
}
}
}
toBeContactedUserRef.set(userData);
})
transaction.get(messageDbRef) ////Third transaction
.then(msgDoc => {
messageDbRef.set({
from: loggedUserId,
to: toBeContactedUserId,
content: message,
reaction: false,
seen: false,
searchId: mergedId,
time: firebase.firestore.FieldValue.serverTimestamp()
})
}
)
})
.then(res=>{
console.log(res);
})
.catch(err=>{
console.log(err);
})
}
handleSubmit()
is the function which is invoked upon clicking a button. In the first transaction.get()
I am doing a write operation. In the second transaction.get()
I am doing a read and a write operation and in the third, I am doing a write operation.
When I am running the code I get error as: Error: Transaction callback must return a Promise
I am not clear if I am using transactions the right way. Is there a way I can write all this logic in a single transaction.get()
Please guide me on how to resolve this error.
You can use Promise.all
to wrap all three promises:
db.runTransaction((transaction) => {
const p1 = transaction.get(loggedUserRef)
.then(userDoc => {
...
})
const p2 = transaction.get(toBeContactedUserRef)
.then(userDoc => {
...
})
const p3 = transaction.get(messageDbRef)
.then(msgDoc => {
...
})
return Promise.all([p1, p2, p3]); // 👈
})
.then(res=>{
console.log(res);
})
.catch(err=>{
console.log(err);
})
Alternatively, you can use async
/ await
to have the compiler generate that for you and get rid of some of the nesting:
db.runTransaction((transaction) => async { // 👈
let userDoc = await transaction.get(loggedUserRef);
...
userDoc = await transaction.get(toBeContactedUserRef);
...
const msgDoc = await transaction.get(messageDbRef)
...
})
.then(res=>{
console.log(res);
})
.catch(err=>{
console.log(err);
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.