我有一个项目将货币详细信息添加到firestore数据库中,我的项目正在使用ionic 3
每当我向集合添加新文档时,触发函数onCreate()将执行并更新名为'更新的文档。
但是触发功能总是显示错误。
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)
sombody请帮忙..
我花了很多时间。
以下是代码:
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;
});
答案 0 :(得分:39)
错误信息是:
Invalid use of type "undefined" as a Firestore argument.
您可以在堆栈跟踪中看到,当您使用DocumentReference上的对象调用set()时,会发生这种情况。事实证明,您在对象中传递的值之一是未定义的。检查您传递的每个值,并确保它们都具有实际值:
.set({
id : id,
branchName : branchName,
currencyName : currencyName,
sellingRate : sellingRate,
buyingRate :buyingRate
});
不可能从错误信息中分辨出它是哪一个,所以你必须将它们全部打印出去做一些检查它们的每一个。
答案 1 :(得分:1)
.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' }
答案 2 :(得分:0)
以下错误消息相对清晰
无效地将类型“
undefined
”用作Firestore参数。
这意味着,在您的set
或update
引用方法中,您传递了一个值为undefined
的参数,即定义不是有效的Firestore参数。
我个人通过示例发现一切都变得更容易理解。
假设我的函数
editStafferPoolPermissions
出现“错误地将类型“ undefined”用作Firestore参数的错误” 错误消息。定义方式如下:export const editStafferPoolPermissions(data: { businessId: string, stafferId: string, poolPermissions: string[], areCustomPermissions: boolean, wage: number, }) => //...
要找出确切的参数(甚至是参数)
这使我们可以看到哪些参数被传递了,哪些没有被传递。
如您所见,我的https云功能的wage
调用中缺少oncall
参数,导致错误崩溃。 这意味着我忘记了传递或错误地传递了wage
参数。
很显然,
undefined
参数会根据您的函数定义方式而有所警惕,但希望这足以使您了解如何跟踪和解决问题。它通常可以归结为两个选项,您要么忘记将其全部传递,要么从前端传递了不正确的信息(或者数据的结构不正确)
undefined
(可选)参数怎么办? Internet上大多数答案不能解决的情况是,我们实际上可能故意留有一个论点undefined
。
实际上,在最长的时间里很难找到它,在这种情况下,我不得不写一个看起来很伪劣的云函数,里面充满了嵌套的if
,当我想创建一个时,允许将可选参数设为undefined
,如果未传递则将其忽略。
要继续前面的示例,假设我们将wage
参数更改为可选参数,即
wage?: number
// ... other params
因此,现在,如果我们调用editStafferPoolPermissions
云函数,那么是否通过工资都没关系。
幸运的是,自May 29 2020起,在SetOptions
上添加了一个名为ignoreUndefinedProperties
的新参数,您可以简单地忽略{{1 }}参数。
例如,我的undefined
的内部可能看起来像这样。
editStafferPoolPermissions
鉴于此新添加的参数是相对较新的,即使在我的工作中,我使用的也是相对较旧的代码库,由于遗留原因,该代码库无法具有最新的Firebase版本,因此,我需要创建一个polyfill ,它会模仿await firestore.collection('staffers').doc(stafferId).set({
poolPermissions,
areCustomPositions,
wage,
}, { ignoreUndefinedProperties: true })
参数。
我创建了以下功能:
ignoreUndefinedProperties
因此,对于我的polyfill,即使在较旧的Firebase版本中,也可以忽略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 })
}
属性。 实际上,即使是在较新的版本上,它实际上也可能有用,因为它使您可以决定是仅在对象根级别还是在潜在的嵌套对象属性上忽略undefined
属性。 strong>
因此,基本上这两个语句是等效的
undefined
await reference.set(data, { ignoreUndefinedProperties: true })
// newer firebase version
请注意,您还可以通过其他await ignoreUndefinedSet(reference, data) // my polyfill
或禁用嵌套对象检查
SetOptions