Home > Mobile >  Firebase transaction completes with null value and no errors
Firebase transaction completes with null value and no errors

Time:09-21

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.

  • Related