Firebase firestore 云函数显示错误:无效使用类型“未定义”作为 Firestore 参数
Posted
技术标签:
【中文标题】Firebase firestore 云函数显示错误:无效使用类型“未定义”作为 Firestore 参数【英文标题】:Firebase firestore cloud functions showing Error: Invalid use of type "undefined" as a Firestore argument 【发布时间】:2018-10-11 06:45:25 【问题描述】:我有一个将货币详细信息添加到 firestore 数据库的项目,我的项目正在使用 ionic 3
每当我向集合中添加新文档时,触发函数 onCreate() 将执行并更新名为“updated”的文档。
但是触发函数总是显示错误。
Error: Invalid use of type "undefined" as a Firestore argument.
at Object.exports.customObjectError.val [as customObjectError] (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/validate.js:164:14)
at Function.encodeValue (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/document.js:808:20)
at Function.encodeFields (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/document.js:678:36)
at Function.fromObject (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/document.js:218:55)
at WriteBatch.set (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/write-batch.js:291:39)
at DocumentReference.set (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/reference.js:419:8)
at Object.<anonymous> (/user_code/lib/index.js:28:10)
at next (native)
at /user_code/lib/index.js:7:71
at __awaiter (/user_code/lib/index.js:3:12)
请大家帮忙..
我花了很多时间。
代码如下:
import * as functions from 'firebase-functions';
const admin = require('firebase-admin');
admin.initializeApp();
exports.createCurrency = functions.firestore
.document('Exchange/ExchangeId')
.onCreate( async (snap, context) =>
const id: string = snap.data().id;
const branchName: string = snap.data().branchName;
const currencyName: string = snap.data().currencyName;
const buyingRate : string = snap.data().buyingRate;
const sellingRate : string = snap.data().sellingRate;
const newUser= admin.
firestore()
.doc(`Exchange/updated`)
.set(
id : id,
branchName : branchName,
currencyName : currencyName,
sellingRate : sellingRate,
buyingRate :buyingRate
);
return newUser;
);
【问题讨论】:
【参考方案1】:错误信息是这样的:
Invalid use of type "undefined" as a Firestore argument.
您可以在堆栈跟踪中看到,当您使用 DocumentReference 上的对象调用 set() 时会发生这种情况。事实证明,您在对象中传递的值之一是未定义的。检查您传递的每个值,并确保它们都具有实际值:
.set(
id : id,
branchName : branchName,
currencyName : currencyName,
sellingRate : sellingRate,
buyingRate :buyingRate
);
无法从错误消息中分辨出它是哪一个,因此您必须将它们全部打印出来并检查每一个。
【讨论】:
是的,我知道了。谢谢您的关心 遇到这个问题,令人困惑的是云函数日志输出没有显示undefined
字段 - 正如你所说,“无法从错误消息中判断它是哪一个,所以你必须……检查每一个。” 只有当我在我的代码中发现我正在访问错误的字段对象时,我才意识到我正在为输入设置一个无效的字段数据地图。我没有意识到如果日志输出中没有显示任何无效字段,我应该检查它。在 Web 客户端上,如果您设置了一个 undefined
字段名称,它可以让您在输出中看到它。很高兴知道【参考方案2】:
当您 .set 一个对象但对象中的一个字段未定义时,您将收到此错误。
问题在于,当您使用console.log 显示对象时,它不会显示未定义的变量,因此难以追踪。
使用以下内容而不是 console.log 来查找导致问题的元素。
const util = require('util');
console.log(util.inspect(myObject, showHidden: false, depth: null));
这将为您提供如下输出:
origin: 'AMS',
destination: undefined,
duration: 94,
carrier: 'KL',
flight_number: '2977',
departure: '2019-06-11T15:34:00',
arrival: '2019-06-11T17:08:00',
type: 'flight'
【讨论】:
【参考方案3】:了解问题:
下面的错误信息比较清楚
无效地将“
undefined
”类型用作 Firestore 参数。
这意味着,在您的 set
或 update
引用方法中,您传递了一个值为 undefined
的参数,根据定义,这不是有效的 Firestore 参数.
解决问题:
我个人觉得举个例子就更容易理解了。
假设我的函数
editStafferPoolPermissions
出现错误,“无效使用类型“未定义”作为 Firestore 参数” 错误消息。其定义如下:export const editStafferPoolPermissions(data: businessId: string, stafferId: string, poolPermissions: string[], areCustomPermissions: boolean, wage: number, ) => //...
找出究竟是哪个参数(甚至参数)
-
打开您的 Firebase 开发者控制台并打开“功能”标签。
选择日志标签
过滤掉函数的确切名称并检查传递的参数
这让我们可以看到,哪些参数被传递,哪些没有。
如您所见,我的https云函数的oncall
调用中缺少wage
参数,导致错误崩溃。 这意味着我要么忘记传递,要么错误传递wage
参数。
显然
undefined
参数会根据您的函数定义方式保持谨慎,但希望这足以让您了解如何跟踪和解决问题的要点。它通常归结为两个选项,您要么完全忘记传递它,要么从前端错误地传递它(或数据结构不正确)
如果我想允许undefined
(可选)参数怎么办?
互联网上的大多数答案都没有解决,我们实际上可能会故意留下一个论点undefined
。
实际上我很长时间都很难找到这个,当我想创建一个时,我不得不求助于编写一个看起来非常劣质的云函数,里面充满了嵌套的if
s,这也允许可选参数为undefined
,如果没有传递则忽略它们。
继续上一个示例,假设我们将 wage
参数更改为可选,即
wage?: number
// ... other params
所以现在,如果我们调用 editStafferPoolPermissions
云函数,工资是否通过都无关紧要。
幸运的是,从 May 29 2020 开始,SetOptions
中添加了一个名为 ignoreUndefinedProperties
的新参数,它允许您简单地忽略 undefined
参数。
例如,我的editStafferPoolPermissions
的内部可能看起来像这样。
await firestore.collection('staffers').doc(stafferId).set(
poolPermissions,
areCustomPositions,
wage,
, ignoreUndefinedProperties: true )
对旧版 Firebase 版本进行故障排除
鉴于这个新添加的参数是相对较新的,即使在我的工作中,我也使用相对较旧的代码库,由于遗留原因无法拥有最新的 firebase 版本,因此,我需要创建一个 polyfill ,这将模仿 ignoreUndefinedProperties
参数。
我创建了以下函数:
export const ignoreUndefinedSet = async (
// depending on your namespace
// & /types version, you can use firebase.firestore.<name> instead
reference: FirebaseFirestore.DocumentReference,
data: FirebaseFirestore.DocumentData,
options?: FirebaseFirestore.SetOptions,
checkNestedObjects = true,
) =>
const isPlainObject = (val: unknown) =>
typeof val === 'object' && val !== null &&
!(val instanceof Date) && !Array.isArray(val)
const keepDefinedProperties = (
obj: FirebaseFirestore.DocumentData,
nestedCheck = true,
) =>
Object.entries(data).reduce(
(result, [key, value]) => (
value === undefined
? result
: (nestedCheck && isPlainObject(value))
? Object.assign(result, [key]: keepDefinedProperties(value) )
: Object.assign(result, [key]: value )
),
)
const onlyDefinedProperties = keepDefinedProperties(data, checkNestedObjects)
await reference.set(onlyDefinedProperties, ...options )
因此,使用我的 polyfill,即使在较旧的 firebase 版本中,您也可以忽略 undefined
属性。 事实上,即使在较新的对象上,它实际上也可能有用,因为它允许您决定是仅在对象根级别忽略 undefined
属性,还是在潜在的嵌套对象属性中忽略。
所以本质上这两个语句是等价的
await reference.set(data, ignoreUndefinedProperties: true )
// newer firebase version
await ignoreUndefinedSet(reference, data) // my polyfill
注意,你也可以通过其他SetOptions
或者禁用嵌套对象检查
await ignoreUndefinedSet(reference, data, merge: true , false)
// does ignoreUndefinedProperties only at root level and uses the merge method
【讨论】:
以上是关于Firebase firestore 云函数显示错误:无效使用类型“未定义”作为 Firestore 参数的主要内容,如果未能解决你的问题,请参考以下文章
是否可以从firebase云函数node.js更新firestore中的map类型字段?
错误:HTTP 错误 400,请求有错误。 Firebase Firestore 云函数
Firebase 云功能与 Firestore 返回“已超过截止日期”