预定的 Firebase 功能 - 不写入 Firestore
Scheduled Firebase Function - No writing to Firestore
我的计划 Cloud Function 按计划 运行 进行,但未成功写入我的 Firestore 实例。当我在本地将它作为 HTTP 请求触发时,代码成功写入 FirestoreDB。但是一旦部署并添加了 PubSub 调度逻辑,它似乎就不会写入 Firestore。
GCP 中的功能日志显示“正常”的完成状态。
想知道我是否正在做一些在 JS 中有效的事情,但 GCP 或 Pubsub 不喜欢,即使它在技术上是有效的 JS?
如有任何帮助或指导,我们将不胜感激。
const admin = require("firebase-admin");
const request = require("request");
const functions = require("firebase-functions");
const serviceAccount = require("......");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
const db = admin.firestore();
exports.scheduledPRRfunction = functions.pubsub
.schedule("every 2 minutes")
.timeZone("America/New_York")
.onRun(((context) => {
const Options = {
"method": "GET",
"url": "...",
"headers": {
"Cookie": ".....",
},
};
db.collection("myCollectionName").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const documentIds = doc.id;
// Delete Documents
db.collection("myCollectionName")
.doc(documentIds).delete().then(() => {
}).catch((error) => {
console.log("Error removing document: ", error);
});
});
});
// Write Documents
request(Options, function(error, response) {
if (error) throw new Error(error);
const apiResponse = JSON.parse(response.body);
const parsedResponse = apiResponse["news_results"];
for (let i = 0; i < parsedResponse.length; i++) {
// console.log(i);
db.collection("myCollectionName").add(parsedResponse[i]);
}
});
}));
request
原生支持回调接口,但不支持 return 承诺,这是您必须在 Pub/Sub 云函数(以及后台云函数)中执行的操作。
官方 Firebase 视频系列对此进行了解释:https://firebase.google.com/docs/functions/video-series/。特别是观看标题为“学习 JavaScript Promises”的三个视频(第 2 部分和第 3 部分特别关注后台触发的 Cloud Functions,但在第 1 部分之前确实值得一看)。
有个request-promise
library that could be used instead, but since Feb 11th 2020 request
is fully deprecated, so I would recommend using axios.
下面的代码应该可以解决问题(未经测试):
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const axios = require('axios');
admin.initializeApp();
const db = admin.firestore();
exports.scheduledPRRfunction = functions.pubsub
.schedule("every 2 minutes")
.timeZone("America/New_York")
.onRun(async (context) => {
try {
const querySnapshot = await db.collection("myCollectionName").get();
const promises = querySnapshot.docs.map(doc => db.collection("myCollectionName").doc(doc.id).delete());
await Promise.all(promises);
const options = {
"method": "get",
"url": "...",
"headers": {
"Cookie": ".....",
},
};
const axiosResponse = await axios(options);
const apiResponse = JSON.parse(axiosResponse.data);
const parsedResponse = apiResponse["news_results"];
const docCreationPromises = parsedResponse.map(response => db.collection("myCollectionName").add(parsedResponse))
await Promise.all(docCreationPromises);
return null;
} catch (error) {
console.log(error);
return null;
}
});
注意:
- 我们使用
async/await
,以便于编写异步代码
- 由于您要并行触发多个异步操作,因此您必须使用
Promise.all()
。
另外请注意,自 Firebase SDK for Cloud Functions 版本 1.0.0 起,firebase-admin
应在 Cloud Functions 运行时内不带任何参数进行初始化,如下所示:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
我的计划 Cloud Function 按计划 运行 进行,但未成功写入我的 Firestore 实例。当我在本地将它作为 HTTP 请求触发时,代码成功写入 FirestoreDB。但是一旦部署并添加了 PubSub 调度逻辑,它似乎就不会写入 Firestore。
GCP 中的功能日志显示“正常”的完成状态。
想知道我是否正在做一些在 JS 中有效的事情,但 GCP 或 Pubsub 不喜欢,即使它在技术上是有效的 JS?
如有任何帮助或指导,我们将不胜感激。
const admin = require("firebase-admin");
const request = require("request");
const functions = require("firebase-functions");
const serviceAccount = require("......");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
const db = admin.firestore();
exports.scheduledPRRfunction = functions.pubsub
.schedule("every 2 minutes")
.timeZone("America/New_York")
.onRun(((context) => {
const Options = {
"method": "GET",
"url": "...",
"headers": {
"Cookie": ".....",
},
};
db.collection("myCollectionName").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const documentIds = doc.id;
// Delete Documents
db.collection("myCollectionName")
.doc(documentIds).delete().then(() => {
}).catch((error) => {
console.log("Error removing document: ", error);
});
});
});
// Write Documents
request(Options, function(error, response) {
if (error) throw new Error(error);
const apiResponse = JSON.parse(response.body);
const parsedResponse = apiResponse["news_results"];
for (let i = 0; i < parsedResponse.length; i++) {
// console.log(i);
db.collection("myCollectionName").add(parsedResponse[i]);
}
});
}));
request
原生支持回调接口,但不支持 return 承诺,这是您必须在 Pub/Sub 云函数(以及后台云函数)中执行的操作。
官方 Firebase 视频系列对此进行了解释:https://firebase.google.com/docs/functions/video-series/。特别是观看标题为“学习 JavaScript Promises”的三个视频(第 2 部分和第 3 部分特别关注后台触发的 Cloud Functions,但在第 1 部分之前确实值得一看)。
有个request-promise
library that could be used instead, but since Feb 11th 2020 request
is fully deprecated, so I would recommend using axios.
下面的代码应该可以解决问题(未经测试):
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const axios = require('axios');
admin.initializeApp();
const db = admin.firestore();
exports.scheduledPRRfunction = functions.pubsub
.schedule("every 2 minutes")
.timeZone("America/New_York")
.onRun(async (context) => {
try {
const querySnapshot = await db.collection("myCollectionName").get();
const promises = querySnapshot.docs.map(doc => db.collection("myCollectionName").doc(doc.id).delete());
await Promise.all(promises);
const options = {
"method": "get",
"url": "...",
"headers": {
"Cookie": ".....",
},
};
const axiosResponse = await axios(options);
const apiResponse = JSON.parse(axiosResponse.data);
const parsedResponse = apiResponse["news_results"];
const docCreationPromises = parsedResponse.map(response => db.collection("myCollectionName").add(parsedResponse))
await Promise.all(docCreationPromises);
return null;
} catch (error) {
console.log(error);
return null;
}
});
注意:
- 我们使用
async/await
,以便于编写异步代码 - 由于您要并行触发多个异步操作,因此您必须使用
Promise.all()
。
另外请注意,自 Firebase SDK for Cloud Functions 版本 1.0.0 起,firebase-admin
应在 Cloud Functions 运行时内不带任何参数进行初始化,如下所示:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();