Have been searching everywhere today and breaking my head to the point that I really don't know anymore what to do with this.
I am trying to do something that sounds simple to me. However the asynchronous workflow breaks me up.
- Find each ID from crawlJobs in Firestore
- Get all the docs of those IDs in another collection
- Add the output to an array
- return the output of the array
Because everything is async i'm getting stuck on number 2 and 3 as number 4 executes faster than the async code is done with.
My big question, how do I handle this?
Here's my full function:
exports.publicOutput = functions
.region("us-central1")
.runWith(runtimeOpts)
.https.onRequest(async (req, res) => {
const projectAlias = req.query.projectalias;
const apiKey = req.query.apikey;
let status = 404;
let data = {
Message:
"Unauthorized access! Please provide the correct authentication data.",
};
let response = data;
let scrapeStorage = [];
// check if credentials are provided
if (!projectAlias || !apiKey) {
return res.status(status).send(response);
}
// when both items provided execute this
if (projectAlias && apiKey) {
const snapshot = await db
.collection("AdaProjects")
.where("projectAlias", "==", projectAlias)
.where("hasAccess", "array-contains", apiKey)
.limit(1)
.get();
if (snapshot.empty) {
return res.status(status).send(response);
}
if (!snapshot.empty) {
snapshot.forEach((doc) => {
projectData = doc.data();
});
status = 200;
}
const crawlJobIDs = projectData.crawlJobs;
let scrapeIDs = [];
crawlJobIDs.forEach(async (jobID) => {
const snapshot = await db
.collection("scrapes")
.where("crawlJobID", "==", jobID)
.get();
if (snapshot.empty) {
console.log("not found jobID", jobID);
return;
}
snapshot.forEach((doc) => {
scrapeIDs.push(doc.id);
console.log(scrapeIDs); // here everything is fine. But this outputs (logically) after "DONE"
});
});
response = scrapeIDs;
}
console.log("DONE");
return res.status(status).send(response);
});
I've also tried to put everythinig in a function and await that before the endpoint of the function.
async function getAllScrapeIDs(crawlJobIDs) {
let someData = [];
try {
crawlJobIDs.forEach(async (jobID) => {
const snapshot = await db
.collection("scrapes")
.where("crawlJobID", "==", jobID)
.get();
if (snapshot.empty) {
console.log("not found jobID", jobID);
return;
}
snapshot.forEach((doc) => {
someData.push(doc.id);
});
});
} catch (error) {
console.log(error);
return null;
}
return someData;
}
// and then later in the code
const crawlJobIDs = projectData.crawlJobs;
response = await getAllScrapeIDs(crawlJobIDs);
Response is still empty as the async code is still not updated.
I have also tried to write everything without async/await and aplied the .then.catch options. Same output. My function finishes before it filled the array with data i want to output.
I find it mindbending as this part const crawlJobIDs = projectData.crawlJobs;
is actually working. Maybe because it only is one item it searches?