测试云功能 - 无法读取未定义的 属性 'data'
Testing Cloud Function - Cannot read property 'data' of undefined
我有一个 Raspberry Pi 并设置了一个天气(和土壤湿度)装置。
我找到了这个指南:https://codelabs.developers.google.com/codelabs/iot-data-pipeline 我按照它进行了操作,但在第 6-7 步时卡住了。
据我了解 - 当我向 PubSub 发送数据时 - 没有任何反应。在 Raspberry End 上,我有点觉得数据正在发送,但没有传递到 BigQuery。我在不同的点做了一些打印语句,试图看看它卡在哪里。
当我试图找出错误时,我慢慢回溯到第 5 步(创建云函数)。
可以在这里看到第 5 步以及我复制的相关代码:https://codelabs.developers.google.com/codelabs/iot-data-pipeline/#4
在 GCP 中 - 我点击云功能 -> function-weatherPubSubToBQ -> 测试(选项卡)
在标题下 - 触发事件 - 我填写了下面的JSON:
{
"sensorID":"Raspberry",
"timecollected":"2020-09-11 06:45:19",
"zipcode":"00000",
"latitude":"0.0",
"longitude":"0.0",
"temperature":"-273",
"humidity":"-1",
"dewpoint":"-273",
"pressure":"0"
}
当我点击 - 测试功能 - 输出如下
**Error: function execution failed. Details:
Cannot read property 'data' of undefined**
Screen capture of JSON and error message
我猜是这两件事之一导致了问题。
event.data 或 PubSubMessage.data
我尝试对代码进行一些更改,但我只是在黑暗中拍摄。
我想知道是否:
- 我做错了什么,这意味着可能还有其他的
其他地方的问题。
- 这个指南有点老了,有
进行了一些更新,使指南中的旧代码不再
根据需要发挥作用。 (不是指南中的 step/image 匹配什么
我在网上看到,截至 2020 年 9 月)
- 如果有人知道哪里出了问题
代码并能够让我知道如何解决它
非常感谢。
提前致谢。
TLDR:该教程已过时,不要使用它,除非你想面对多个问题并想在困难中学习
我完成了教程并且能够重现这个问题..等等。正如您已经提到的那样,教程已经过时并且很多东西都发生了变化,您可以通过查看图像并注意到 UI 甚至有所不同来推断,所以我不会向任何人推荐本教程GCP 新手。
第一期:
**Error: function execution failed. Details: Cannot read property 'data' of undefined**
可以通过查看 pub/sub 消息中预期的 structure 轻松解决:
{
"data": string,
"attributes": {
string: string,
...
},
"messageId": string,
"publishTime": string,
"orderingKey": string
}
这么简单吧?然而,一旦你像我一样用自己的变量模仿消息的结构:
{
"data": "",
"attributes": {
"sensorID":"Raspberry",
"timecollected":"2020-09-11 06:45:19",
"zipcode":"00000",
"latitude":"0.0",
"longitude":"0.0",
"temperature":"-273",
"humidity":"-1",
"dewpoint":"-273",
"pressure":"0"
},
"messageId": "id_1",
"publishTime": "2014-10-02T15:01:23Z",
"orderingKey": ""
}
您将收到关于 JSON:
的错误
SyntaxError: Unexpected token ' in JSON at position 1
这个错误是由于在变量incomingData
内部构造JSON时使用了'
所以你必须改变第一个变量声明,我通过使用模板文字:
const incomingData = PubSubMessage.data ? Buffer.from(PubSubMessage.data, 'base64').toString() : `{"sensorID": "na","timecollected":"01/01/1970 00:00:00","zipcode":"00000","latitude":"0.0","longitude":"0.0","temperature":"-273","humidity":"-1","dewpoint":"-273","pressure":"0"}`;
但是问题还没有结束,在尝试插入 BigQuery 时进行了一些测试后,我收到了有关插入的错误,但不知道到底发生了什么,所以我隔离了在外部脚本中咨询,发现 错误处理是错误的 ,我建议您首先更改的是 package.json
中的 BigQuery
版本,来自:
"@google-cloud/bigquery": "^0.9.6"
进入
"@google-cloud/bigquery": "5.2.0"
这是撰写此答案时的最新版本。下一部分是将您使用 BigQuery
构造函数的方式重新定义为:
const bigquery = new BigQuery({
projectId: projectId
});
然后经过多次测试,我发现 catch
没有按预期完成它的工作,因此必须将那部分重写为:
bigquery
.dataset(datasetId)
.table(tableId)
.insert(rows)
.then((foundErrors) => {
rows.forEach((row) => console.log('Inserted: ', row));
if (foundErrors && foundErrors.insertErrors != undefined) {
foundErrors.forEach((err) => {
console.log('Error: ', err);
})
}
})
.catch((err) => {
bigquery
.dataset(datasetId)
.table(tableId)
.insert(rows)
.then((foundErrors) => {
rows.forEach((row) => console.log('Inserted: ', row));
if (foundErrors && foundErrors.insertErrors != undefined) {
foundErrors.forEach((err) => {
console.log('Error: ', err);
})
}
})
.catch((err) => {
if(err.name=='PartialFailureError'){
if (err && err.response.insertErrors != undefined) {
err.response.insertErrors.forEach((errors) => {
console.log(errors);
})
}
}else{
console.log("GENERIC ERROR:",err)
}
});
});
在此之后您最终会注意到错误是由于(再次)incomingData
变量造成的:
Could not parse \'01/01/1970 00:00:00\' as a timestamp. Required format is YYYY-MM-DD HH:MM[:SS[.SSSSSS]]'
您必须将日期从 01/01/1970 00:00:00
更改为 1970-01-01 00:00:00
。
还在我身边吗?那么在 CF 末尾使用 callback
会产生另一个错误:
这是因为 Cloud Functions 现在需要三个 parameters 而回调是最后一个,因此将函数声明更改为:
exports.subscribe = function (event, context, callback)
完成所有这些之后,您已经能够将数据插入 BigQuery,但是我们使用的是局部变量而不是来自 pub/sub 的数据,此时我放弃了,因为我需要通过使用 Attributes 而不是 data
.
实际上重写整个函数以使其工作
所以如前所述,如果您刚开始接触 GCP 世界,请不要遵循本教程。
我有一个 Raspberry Pi 并设置了一个天气(和土壤湿度)装置。
我找到了这个指南:https://codelabs.developers.google.com/codelabs/iot-data-pipeline 我按照它进行了操作,但在第 6-7 步时卡住了。
据我了解 - 当我向 PubSub 发送数据时 - 没有任何反应。在 Raspberry End 上,我有点觉得数据正在发送,但没有传递到 BigQuery。我在不同的点做了一些打印语句,试图看看它卡在哪里。
当我试图找出错误时,我慢慢回溯到第 5 步(创建云函数)。 可以在这里看到第 5 步以及我复制的相关代码:https://codelabs.developers.google.com/codelabs/iot-data-pipeline/#4
在 GCP 中 - 我点击云功能 -> function-weatherPubSubToBQ -> 测试(选项卡)
在标题下 - 触发事件 - 我填写了下面的JSON:
{
"sensorID":"Raspberry",
"timecollected":"2020-09-11 06:45:19",
"zipcode":"00000",
"latitude":"0.0",
"longitude":"0.0",
"temperature":"-273",
"humidity":"-1",
"dewpoint":"-273",
"pressure":"0"
}
当我点击 - 测试功能 - 输出如下
**Error: function execution failed. Details:
Cannot read property 'data' of undefined**
Screen capture of JSON and error message
我猜是这两件事之一导致了问题。 event.data 或 PubSubMessage.data
我尝试对代码进行一些更改,但我只是在黑暗中拍摄。
我想知道是否:
- 我做错了什么,这意味着可能还有其他的 其他地方的问题。
- 这个指南有点老了,有 进行了一些更新,使指南中的旧代码不再 根据需要发挥作用。 (不是指南中的 step/image 匹配什么 我在网上看到,截至 2020 年 9 月)
- 如果有人知道哪里出了问题 代码并能够让我知道如何解决它 非常感谢。
提前致谢。
TLDR:该教程已过时,不要使用它,除非你想面对多个问题并想在困难中学习
我完成了教程并且能够重现这个问题..等等。正如您已经提到的那样,教程已经过时并且很多东西都发生了变化,您可以通过查看图像并注意到 UI 甚至有所不同来推断,所以我不会向任何人推荐本教程GCP 新手。
第一期:
**Error: function execution failed. Details: Cannot read property 'data' of undefined**
可以通过查看 pub/sub 消息中预期的 structure 轻松解决:
{
"data": string,
"attributes": {
string: string,
...
},
"messageId": string,
"publishTime": string,
"orderingKey": string
}
这么简单吧?然而,一旦你像我一样用自己的变量模仿消息的结构:
{
"data": "",
"attributes": {
"sensorID":"Raspberry",
"timecollected":"2020-09-11 06:45:19",
"zipcode":"00000",
"latitude":"0.0",
"longitude":"0.0",
"temperature":"-273",
"humidity":"-1",
"dewpoint":"-273",
"pressure":"0"
},
"messageId": "id_1",
"publishTime": "2014-10-02T15:01:23Z",
"orderingKey": ""
}
您将收到关于 JSON:
的错误SyntaxError: Unexpected token ' in JSON at position 1
这个错误是由于在变量incomingData
内部构造JSON时使用了'
所以你必须改变第一个变量声明,我通过使用模板文字:
const incomingData = PubSubMessage.data ? Buffer.from(PubSubMessage.data, 'base64').toString() : `{"sensorID": "na","timecollected":"01/01/1970 00:00:00","zipcode":"00000","latitude":"0.0","longitude":"0.0","temperature":"-273","humidity":"-1","dewpoint":"-273","pressure":"0"}`;
但是问题还没有结束,在尝试插入 BigQuery 时进行了一些测试后,我收到了有关插入的错误,但不知道到底发生了什么,所以我隔离了在外部脚本中咨询,发现 错误处理是错误的 ,我建议您首先更改的是 package.json
中的 BigQuery
版本,来自:
"@google-cloud/bigquery": "^0.9.6"
进入
"@google-cloud/bigquery": "5.2.0"
这是撰写此答案时的最新版本。下一部分是将您使用 BigQuery
构造函数的方式重新定义为:
const bigquery = new BigQuery({
projectId: projectId
});
然后经过多次测试,我发现 catch
没有按预期完成它的工作,因此必须将那部分重写为:
bigquery
.dataset(datasetId)
.table(tableId)
.insert(rows)
.then((foundErrors) => {
rows.forEach((row) => console.log('Inserted: ', row));
if (foundErrors && foundErrors.insertErrors != undefined) {
foundErrors.forEach((err) => {
console.log('Error: ', err);
})
}
})
.catch((err) => {
bigquery
.dataset(datasetId)
.table(tableId)
.insert(rows)
.then((foundErrors) => {
rows.forEach((row) => console.log('Inserted: ', row));
if (foundErrors && foundErrors.insertErrors != undefined) {
foundErrors.forEach((err) => {
console.log('Error: ', err);
})
}
})
.catch((err) => {
if(err.name=='PartialFailureError'){
if (err && err.response.insertErrors != undefined) {
err.response.insertErrors.forEach((errors) => {
console.log(errors);
})
}
}else{
console.log("GENERIC ERROR:",err)
}
});
});
在此之后您最终会注意到错误是由于(再次)incomingData
变量造成的:
Could not parse \'01/01/1970 00:00:00\' as a timestamp. Required format is YYYY-MM-DD HH:MM[:SS[.SSSSSS]]'
您必须将日期从 01/01/1970 00:00:00
更改为 1970-01-01 00:00:00
。
还在我身边吗?那么在 CF 末尾使用 callback
会产生另一个错误:
这是因为 Cloud Functions 现在需要三个 parameters 而回调是最后一个,因此将函数声明更改为:
exports.subscribe = function (event, context, callback)
完成所有这些之后,您已经能够将数据插入 BigQuery,但是我们使用的是局部变量而不是来自 pub/sub 的数据,此时我放弃了,因为我需要通过使用 Attributes 而不是 data
.
所以如前所述,如果您刚开始接触 GCP 世界,请不要遵循本教程。