我有一个由http请求触发的云函数,它打算执行以下操作:
-
根据查询得到一定数量的文档。
-
对查询的每个文档执行读取操作。
-
从(2)获取新文档后,执行一些读/写操作(从子集合中删除、将文档添加到另一个子集合,以及更新根集合中的文档)。
因此,我需要等待(2)和(3)循环,然后执行批处理操作的东西。
下面是我目前拥有的代码,当我在本地测试函数时,这些代码正在工作。但是我不能将它部署到firebase,因为它有承诺错误,比如“每次都必须返回承诺”和“避免嵌套承诺”。
exports.finishEvents = functions.https.onRequest((req, res) => {
const eventsRef = admin.firestore().collection('events');
var currentTime = new Date().getTime();
var currentTimeMinus1h = currentTime - 3600000;
console.log('----- finishEvents started -----')
const queryRef = eventsRef.where('finished', '==', false).where('date', '<=', new Date(currentTimeMinus1h)).get().then(function(querySnapshot){
if (querySnapshot.size > 0) {
querySnapshot.forEach(function(doc) {
var owner_id = doc.data().owner_id;
var event_id = doc.id;
console.log(owner_id, event_id);
var userEventOwnerGoingRef = admin.firestore().collection("user_events").doc(owner_id).collection('going').doc(event_id);
userEventOwnerGoingRef.get().then(doc2 => {
if (!doc2.exists) {
console.log('No such document!');
} else {
console.log('Document data:', doc2.data());
var goingIds = doc.data().going_ids;
console.log('GOING IDS', goingIds);
var batch = admin.firestore().batch();
for (var userId in goingIds) {
if (goingIds.hasOwnProperty(userId)) {
console.log(userId + " -> " + goingIds[userId]);
var eventRef = admin.firestore().collection("events").doc(event_id);
var userEventGoingRef = admin.firestore().collection("user_events").doc(userId).collection('going').doc(doc2.id);
var userEventAttendedRef = admin.firestore().collection("user_events").doc(userId).collection('attended').doc(doc2.id);
batch.set(userEventAttendedRef, doc2.data());
batch.delete(userEventGoingRef)
if (userId == doc2.data().owner_id) batch.update(eventRef, {finished: true});
}
}
batch.commit().then(function () {
return res.status(200).send("Done.");
});
}
})
.catch(err => {
console.log('Error getting userEventOwnerGoingRef', err);
return res.status(200).send("Finished.");
});
});
} else {
console.log("No events found");
return res.status(200).send("Finished.");
}
})
.catch(err => {
console.log('Error getting events', err);
return res.status(200).send("Finished.");
});
});
当我在本地测试它时,即使工作已经完成,我也会收到一个错误,指出
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Can't set headers after they are sent.
我可以看到,我正在为原始查询的每个文档发送结果,而完成云功能只需要发送一次结果。
我想我需要返回承诺,然后在步骤(2)和(3)完成后执行我的所有事务的批处理。然而,这是我第一次使用javascript,我正在努力解决这个问题。任何帮助都将不胜感激。