Firebase云功能Firestore触发onWrite在本地测试时未按预期运行

Posted

技术标签:

【中文标题】Firebase云功能Firestore触发onWrite在本地测试时未按预期运行【英文标题】:Firebase cloud function Firestore trigger onWrite not behaving as expected when testing locally 【发布时间】:2019-02-11 04:19:05 【问题描述】:

我正在使用 Firebase Functions Shell 在 Node 中本地测试 Firestore 触发的 Firebase Cloud Function。

当使用 onWrite 触发器并通过从函数 shell 调用 updateMonth(foo:'new') 传递新文档时,我无法获得对新文档的引用。

exports.updateMonth = functions.firestore
.document('users/userId').onWrite((change, context) => 
    const document = change.after.exists ? change.after.data() : null;
    console.log("change.after.exists", change.after.exists)
    console.log("change.before.exists", change.before.exists)
    const oldDocument = change.before.data();
    console.log("Old:",oldDocument)
    return true
)

当同时调用 before 和 after 来模拟文档更新 updateMonth(before:foo:'old',after:foo:'new') 时,它按预期工作。 但是,当仅使用 updateMonth(foo:'new') 调用时,前后文档似乎都不存在:

i  functions: Preparing to emulate functions.
Warning: You're using Node.js v8.4.0 but Google Cloud Functions only supports v6.11.5.
+  functions: hi
+  functions: helloWorld
+  functions: updateMonth
firebase > updateMonth(before:foo:'old',after:foo:'new')
'Successfully invoked function.'
firebase > info: User function triggered, starting execution
info: change.after.exists true
info: change.before.exists true
info: Old:  foo: 'old' 
info: Execution took 20 ms, user function completed successfully

firebase > updateMonth(foo:'new')
'Successfully invoked function.'
firebase > info: User function triggered, starting execution
info: change.after.exists false
change.before.exists false
Old: undefined
Execution took 2 ms, user function completed successfully

我不确定如何获得对正在创建的新文档的引用。在这种情况下,我希望 change.after.exists 是正确的。

【问题讨论】:

您的问题有点身份问题。你说它是一个 onWrite 触发器,但你已经展示了一个 onUpdate 触发器。 onUpdate 仅在修改现有文档时触发,beforeafter 文档应始终存在。 onWrite 将触发任何更改(您必须小心检查发生了什么)。你想在这里完成什么? 我的错。感谢您指出 Doug,我已经使用 onWrite 触发器再次测试了代码,并添加了完整的控制台输出以进行澄清。 【参考方案1】:

使用 onWrite 和 onUpdate 触发器,您需要在所有情况下声明文档的“之前”和“之后”状态。您不能尝试通过省略“之前”或“之后”键来简化 API。例如,如果您只想测试文档创建,请尝试以下操作:

updateMonth(
    after:foo:'new'
)

另外,如果您的代码只对文档创建感兴趣,那么只在 onCreate 触发器上编写代码可能比尝试在 onWrite 中找出文档状态更容易。就个人而言,我避免使用 onWrite 并使用其他三个,因为它们更容易推断出实际进行了哪些更改。

【讨论】:

谢谢道格!刚刚得出了同样的结论:)【参考方案2】:

经过多次迭代,结果证明解决方案非常简单。 要成功模拟在使用 firebase 函数 shell 在本地模拟云功能时将触发 onWrite 的新文档创建,您需要显式提供 after 属性,如 updateMonth(after:foo:'newVal')

firebase > updateMonth(after:foo:'newVal')
'Successfully invoked function.'
firebase > info: User function triggered, starting execution
change.after.exists true
change.before.exists false
New:  foo: 'newVal' 
info: Execution took 291 ms, user function completed successfully

https://firebase.google.com/docs/functions/local-emulator#invoke_firestore_functions 的文档没有明确说明这一点,因此造成了混乱。也许这可能是添加到firebase-tools firebase functions:shell 的一个很好的增强功能。

【讨论】:

以上是关于Firebase云功能Firestore触发onWrite在本地测试时未按预期运行的主要内容,如果未能解决你的问题,请参考以下文章

Firebase Firestore +云功能服务器端验证应用内购买收据(Swift + NodeJS)

在云功能上使用 Firestore SDK 时出现错误:无法编码类型

使用 Python 的 Firebase 云函数?

Firebase 云功能 / Firestore

Firebase 云功能与 Firestore 返回“已超过截止日期”

您如何避免使用 firebase 云功能可能出现的竞争情况?