谷歌云功能在访问实时数据库时返回 204 状态
Posted
技术标签:
【中文标题】谷歌云功能在访问实时数据库时返回 204 状态【英文标题】:Google cloud function returning 204 status when accessing realtime database 【发布时间】:2018-08-10 16:46:25 【问题描述】:我有一个通过 firebase 托管的用于测试目的的网站,将客户端信息存储在需要稍后访问的实时数据库中。当我通过带有访问我的实时数据库的脚本的单个 html 文档执行此操作时,我能够成功找到信息,但是当我将相同的逻辑复制并粘贴到云函数中时,它不起作用。我已经尝试了我能想到的一切,现在当我运行该函数时,它会执行两次(我不知道为什么)。第一次执行以 http 204 状态结束(未找到内容)。第二次执行返回 http 500 内部服务错误。当我检查 firebase 上的日志时,它说错误是因为“accounts.getValue() 不是函数”。我认为发生的事情是在第一次执行时,该函数无法找到帐户,并且在没有尝试找到帐户的情况下再次执行,这可能是它无法运行 accounts.getValue()
的原因我想我的主要问题是为什么我的函数无法找到帐户?
geturl 是我遇到问题的函数
我的实时数据库的结构是 数据库名称
-accounts
-some data
-more data
-more account data
-ActiveQRs
-some data...
我的云函数 index.js 文件是
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')(origin: true);
var firebase = require("firebase");
var admin = require("firebase-admin");
require("firebase/auth");
require("firebase/database");
//require("firebase/firestore");
//require("firebase/messaging");
require("firebase/functions");
var serviceAccount = require("./serviceKey.json");
// Initialize the app with a service account, granting admin
//privileges
admin.initializeApp(
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com"
);
const displayqr = express();
const geturl = express();
displayqr.get('/displayqr', (request, response) =>
console.log("response sent");
response.send("testio/qrdisplay.html");
);
exports.displayqr = functions.https.onRequest(displayqr);
exports.geturl = functions.https.onCall((email) =>
const mail = email.toString();
var result = "";
result = result + mail;
var accounts =
admin.database().ref("livsuiteform/accounts");
result = (accounts.getValue());
accounts.orderByKey().on("value", function(snapshot)
snapshot.forEach(function(data)
if (data.child("Email").val() == mail)
var firstName = data.child("FirstName").val();
var lastName = data.child("LastName").val();
result = firstname;
result = "if loop entered";
// end if
// return "name not found";
); // end for each
); // end order by
return result;
);
【问题讨论】:
PS 我希望此函数在从外部网站调用时读取数据库日期,而不是在数据库写入或任何其他类型的事件中 您是否从控制台中的 firebase 获取快照数据? 在网站控制台上没有显示任何内容,因为该功能正在服务器上运行,但在 firebase 日志中我没有看到任何消息日志,我无法在任何地方查看console.log,这就是为什么我的结果是一个字符串,最终我希望它返回一个url,但我一直在返回我的结果并将其用作调试控制台 当我执行 result = snapshot.getValue(); 时,我无法看到快照数据 【参考方案1】:TLDR;关注tutorial,了解如何为您的移动应用构建和部署可调用函数。
您的功能无法按预期工作的原因有多种。
-
您将包含 Firebase 的客户端版本 (
var firebase = require("firebase");
)。您不应该使用甚至不需要客户端版本。相反,只需使用 Firebase 管理员 (docs) 来访问任何数据。如果您在从 Admin SDK 访问数据库时需要某些用户权限,here 是一个很好的例子来说明如何实现这一点(向下滚动到“您仍然可以执行用户授权的更改...”)。
您混合了不同的 Admin SDK 引用。 getValue()
是 Java 管理 SDK 的一部分。您应该使用等效的 javascript val()
。此外,在您的代码中,accounts
是 Reference
而不是 DataSnapshot
。
您没有返回您的Promise
。这可能是您以后函数执行不一致的原因SO Question。
您没有从初始函数返回任何内容。如果您不返回任何内容,那么您的应用程序将不会返回任何内容。解决方法同3的解决方法:返回你的Promise
。
您不应在 Firebase 函数中使用 on
。你应该使用once
。不同之处在于 on
不会返回 Promise
而 once
会。它返回一个用于分离监听器的函数。
我知道这是很多要点并指出您的代码中的问题,但我只是不想给出一个肤浅的答案,这导致您又问了一个问题并等待了大约 2 个小时(在撰写本文时) 的答案。
我希望这会有所帮助!
代码
exports.geturl = functions.https.onCall((email) =>
const mail = email.toString();
var result = "";
result = result + mail;
var accounts = admin.database().ref("livsuiteform/accounts");
return accounts.orderByKey().once("value")
.then(function (snapshot)
snapshot.forEach(function (data)
if (data.child("Email").val() == mail)
var firstName = data.child("FirstName").val();
var lastName = data.child("LastName").val();
result = firstName;
result = "if loop entered";
// end if
// return "name not found";
); // end for each
return result;
); // end order by
);
【讨论】:
感谢 Bryan,这对我有帮助,我想我仍然很难处理承诺,哪些代码行需要承诺,我该如何返回?我用一次替换,但我的函数仍然执行两次,并且运行应该非常快时需要大约 2 秒 @DHolthaus 我添加了一些应该让它正常运行的代码。geturl
应该与上面的类似。我建议浏览我链接的教程。
我认为现在看起来几乎完全像我的代码,但它仍然没有从数据库中检索信息,我不确定为什么。现在,当我调用该函数时(现在我的应用程序将函数的结果记录到控制台)它返回使用的电子邮件,这意味着结果 = 结果 + 邮件;工作,但其他陈述没有。现在在 firebase 日志中,我的函数每次调用都会运行 3 次,第三次调用会返回一个错误,指出未定义名字。
我浏览了这个教程,但它主要是在客户端,我没有看到太多关于 Promise 的内容,你能告诉我你做了什么改变吗?我能看到的唯一变化是改为一次并使用 .then
@DHolthaus 我改变了很多。我通过返回 accounts.orderByKey()...
返回了 Promise
。我修复了firstname
与firstName
不同。我删除了函数return result;
末尾的返回。如果您复制/粘贴我提供的代码,您应该会看到结果将是 email
或 firstName
。以上是关于谷歌云功能在访问实时数据库时返回 204 状态的主要内容,如果未能解决你的问题,请参考以下文章