Firebase 事务以空值完成且没有错误

Firebase transaction completes with null value and no errors

问题有点类似于。但是,我已经有了建议的解决方案。

以下使用 Firebase web 版本 9。运行 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());

在你继续说之前,我没有将节点设置为空对象,我希望它稍后已经成为一个对象。

这是我的输出。

1 null
2 null
1 {otherMeta: {…}}
2 {otherMeta: {…}, ready: true}
3 null

如您所见,交易完成时为空值。这很奇怪。

我正要提交针对 SDK 的回归错误,当我注意到这似乎来自 async 关键字时。

如果我使用此代码:

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());
});

我得到最后一个日志的输出为:

3 null

当我删除 async 关键字(无论如何都不需要)时,我得到:

3 {a: true, ready: true}

我的测试床:https://stackblitz.com/edit/firebase-v9-rtdb

我不知道 async 关键字可能会导致它。尽管如前所述,关键字在我的代码段中不是必需的,但您的代码中需要它,而且我看不出它会如何影响结果。

TL;DR: 只需删除 async 关键字。

弗兰克把它钉在了头上,但我会写下一个单独的答案,这样我就可以使用语法高亮显示了。如果你有两个相同的函数:

function theAnswer() { return 42; }
async function theEventualAnswer() { return 42; }

这两个函数的行为非常不同。第一个 returns 字面量 42。第二个居然returnsPromise.resolve(42)。如果您尝试添加 theAnswer() + 1,您会得到 43。如果你尝试添加 theEventualAnswer() + 1 你会得到 '[object Promise]1'.

在这种情况下,您返回了 Promise.resolve({...node, ready: true}),随后 SDK tries to turn into a Reference 得到了一些非常奇怪的结果,因为它需要具体类型。

我已代表您提交 a bug,详细说明团队如何向您提供编译时错误消息。