When working with promises (such as in Knex queries), Javascript will move on to the next statement without waiting for the previous one to complete. This is the issue you are facing: your code initiates all the database inserts, but does not wait for them to finish before executing the query to retrieve the data.
Since you are looping through a series of files, using Promise.all
would be an effective solution. Here is how it operates. First, gather all the promises:
const insertions = fileArray.map(file => {
fileLocation = fileArray[i].location;
imgLocationArray.push(fileLocation);
return knex("files")
.insert({
fileLink: fileLocation,
todoId: todoId,
userId: userId
})
})
Take note of the return
statement here, as it is crucial. Next, we must await the completion of all these promises:
Promise.all(insertions)
.then(() => knex("files").where("files.userId", userId))
.then(userFiles => {
console.log("Error occurred");
res.json({
userFiles: userFiles
});
})
.catch(err => console.log(err));
Only within this final .then
block can we rely on the availability of the data to us, since all preceding queries have finished.
If you are fortunate enough to work in an environment on your server where async
/await
is supported (Node versions after 7.6), you can utilize the following approach:
try {
await Promise.all(insertions);
const userFiles = await knex("files").where("files.userId", userId);
res.json({ userFiles });
} catch (e) {
// Handle any database errors
}
Many individuals find this syntax more easily understandable. Remember that the function containing this code must be defined with the async
keyword:
myExpressRouter.post("userfiles", async (req, res) => {
// ...
})