The question is somewhat similar to Firebase transaction returns null and completes without error . However, I already had the suggested solution.
The following uses Firebase web version 9. Running in node v14.17.3
const returnVal = await runTransaction(firebaseRef, async node => {
console.log("1", node);
if (node && node.ready != true) {
node.ready = true;
}
console.log("2", node);
return node;
});
if (!returnVal.committed) throw new Error("Not committed");
console.log("3", returnVal.snapshot.toJSON());
Before you go ahead and say, I am not setting node as an empty object, I expect it to become an object later on already.
And here is my output.
1 null
2 null
1 {otherMeta: {…}}
2 {otherMeta: {…}, ready: true}
3 null
As you can see, the transaction is completed with a null value. Which is strange.
CodePudding user response:
I was about to file a regression bug against the SDK, when I noticed that this seems to come from the async
keyword.
If I use this code:
runTransaction(firebaseRef, async (node) => {
console.log("1", node);
if (node && node.ready != true) {
node.ready = true;
}
console.log("2", node);
return node;
}).then((result) => {
if (!result.committed) throw new Error("Not committed");
console.log("3", result.snapshot.toJSON());
});
I get the output for the last log as:
3 null
When I remove only the async
keyword (which is not needed anyway), I get:
3 {a: true, ready: true}
My test bed: https://stackblitz.com/edit/firebase-v9-rtdb
I have no what about the async
keyword could be causing it. Although as said the keyword is unnecessary in my snippet, it's needed in your code and I don't see how it would affect the result.
CodePudding user response:
TL;DR: just remove the async
keyword.
Frank nailed it on the head, but I'm going to write down a separate answer so that I can use syntax highlighting. If you have two identical functions:
function theAnswer() { return 42; }
async function theEventualAnswer() { return 42; }
These two functions behave very differently. The first one returns the literal 42
. The second one actually returns Promise.resolve(42)
. If you try to add theAnswer() 1
you get 43
. If you try to add theEventualAnswer() 1
you get '[object Promise]1'
.
In this case, you've returned Promise.resolve({...node, ready: true})
, which the SDK later tries to turn into a Reference and gets some pretty weird results because it expects concrete types.
I've filed a bug on your behalf that details how the team could have provided you with a compile-time error message.