我遇到了一个无法调试的小问题。我编写了一个小的Firebase函数来从JSON对象获取数据,并将其存储在Firestore文档中。易于理解的
它是有效的,除了部署后第一次运行它(或者自上次执行以来已经过了很长时间(。我必须运行它一次(不工作(,然后后续的尝试总是有效的,我可以看到创建的新文档中有所有的数据
在第一次尝试中,没有日志:函数执行耗时601毫秒,完成时状态代码为:200。尽管如此,没有创建任何文档,也没有进行任何更改。
在第二次和随后的尝试中,如果我使用HTTPPOST请求函数执行https://cloudfunctions/functionName?id=12345,然后在集合中创建文档"12345",其中包含所有数据。
在执行任何函数调用之前,存储文档的集合(场景(已存在于数据库中。
这是代码:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
db.settings({ignoreUndefinedProperties: true});
const fetch = require("node-fetch");
let scenarioData;
const fetchScenarioJSON = async (scenarioId) => {
try {
const response = await fetch(`https://url/api/scenarios/single/${scenarioId}`);
const scenarioText = await response.text();
scenarioData = JSON.parse(scenarioText);
} catch (err) {
return ("not valid json");
}
return scenarioData;
};
/**
* Add data to Firestore.
* @param {JSON} scenario JSON array containing the scenario data.
*/
async function addDataToFirestore(scenario) {
const data = {
id: scenario.scenario._id,
name: scenario.scenario.name,
description: scenario.scenario.description,
language: scenario.scenario.language,
author: scenario.scenario.author,
draft: scenario.scenario.draft,
last_modified: scenario.scenario.last_modified,
__v: scenario.scenario.__v,
duration: scenario.scenario.duration,
grade: scenario.scenario.grade,
deleted: scenario.scenario.deleted,
view_count: scenario.scenario.view_count,
comments_count: scenario.scenario.comments_count,
favorites_count: scenario.scenario.favorites_count,
activities_duration: scenario.scenario.activities_duration,
activities: scenario.scenario.activities,
outcomes: scenario.scenario.outcomes,
tags: scenario.scenario.tags,
students: scenario.scenario.students,
created: scenario.scenario.created,
subjects: scenario.scenario.subjects,
};
const res = await db.collection("scenarios").doc(scenario.scenario._id).set(data);
}
exports.functionName =
functions.https.onRequest((request, response) => {
return fetchScenarioJSON(request.query.id).then((scenario) => {
if (typeof scenario === "string") {
if (scenario.includes("not valid json")) {
response.send("not valid json");
}
} else {
addDataToFirestore(scenario);
response.send(`Done! Added scenario with ID ${request.query.id} to the app database.`);
}
});
});
我的问题是,我是否对代码做了任何错误的处理,使执行在部署后的第一个调用中不起作用,但在随后的调用中确实起作用。
这很可能是因为您没有等到异步addDataToFirestore()
函数完成后再发送回响应。
通过进行
addDataToFirestore(scenario);
response.send()
您实际上向Cloud Function平台指示(使用response.send()
(它可以终止并清理Cloud Function(有关更多详细信息,请参阅文档(。由于您不等待异步addDataToFirestore()
函数完成,因此不会将文档写入Firestore。
";"不稳定";行为(有时有效,有时无效(可以解释如下:
- 在某些情况下,您的云函数在对Firestore的写入完全执行之前就终止了,如上所述
- 但是,在其他一些情况下,云功能平台可能不会立即终止CF,从而为完全执行对Firestore的写入提供足够的时间。这很可能是第一次调用后发生的情况:Cloud函数的实例仍在运行,然后用";后续呼叫">
以下修改应该可以完成任务(未经测试(。我已经用async/await重构了Cloud函数,因为您在其他函数中使用了它。
// ....
async function addDataToFirestore(scenario) {
const data = {
id: scenario.scenario._id,
name: scenario.scenario.name,
description: scenario.scenario.description,
language: scenario.scenario.language,
author: scenario.scenario.author,
draft: scenario.scenario.draft,
last_modified: scenario.scenario.last_modified,
__v: scenario.scenario.__v,
duration: scenario.scenario.duration,
grade: scenario.scenario.grade,
deleted: scenario.scenario.deleted,
view_count: scenario.scenario.view_count,
comments_count: scenario.scenario.comments_count,
favorites_count: scenario.scenario.favorites_count,
activities_duration: scenario.scenario.activities_duration,
activities: scenario.scenario.activities,
outcomes: scenario.scenario.outcomes,
tags: scenario.scenario.tags,
students: scenario.scenario.students,
created: scenario.scenario.created,
subjects: scenario.scenario.subjects,
};
await db.collection("scenarios").doc(scenario.scenario._id).set(data);
}
exports.functionName =
functions.https.onRequest(async (request, response) => {
try {
const scenario = await fetchScenarioJSON(request.query.id);
if (typeof scenario === "string") {
if (scenario.includes("not valid json")) {
response.send("not valid json");
}
} else {
await addDataToFirestore(scenario); // See the await here
response.send(`Done! Added scenario with ID ${request.query.id} to the app database.`);
}
} catch (error) {
// ...
}
});