У меня есть облачная функция, запускаемая запросом 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 и борюсь с этим.Любая помощь будет оценена.