The code works and uploads images to Backblaze but it's not waiting for the for loop to finish running and the query to finish before calling next. If I console log the file ids it will list the ids 3 or four seconds after next() has been called!
import fs from "fs";
import B2 from "backblaze-b2";
import path from "path";
import dotenv from "dotenv";
dotenv.config();
export const uploadToBackBlaze = async (req, res, next) => {
console.log("I'm here uploading to Backblaze");
const b2 = new B2({
applicationKeyId: process.env.BACKBLAZE_ACCOUNT_ID,
applicationKey: process.env.BACKBLAZE_MASTER_APPLICATION_ID,
});
const __dirname = path.resolve();
let tempDir = path.join(__dirname, "chapterTemp");
const imageIds = [];
try {
b2.authorize()
.then(async () => {
const bucketId = process.env.BACKBLAZE_BUCKET_ID;
fs.readdir(tempDir, async function (err, files) {
if (err) {
console.error(err);
res.sendStatus(500).json({ message: err.message });
return;
}
for (const file of files) {
const fileData = fs.readFileSync(path.join(tempDir, file));
const uploadFileName = path.join(file);
const uploadUrl = await b2.getUploadUrl(bucketId);
const response = await b2.uploadFile({
uploadUrl: uploadUrl.data.uploadUrl,
uploadAuthToken: uploadUrl.data.authorizationToken,
filename: uploadFileName,
data: fileData,
mime: "image/png" || "image/jpg" || "image/jpeg" || "image/webp", // replace with the appropriate MIME type for your files
});
console.log(response.data.fileId);
imageIds.push(response.data.fileId);
}
});
})
.then(() => {
console.log(imageIds);
req.imageIds = imageIds;
next();
});
} catch (error) {
console.log(error);
return res.status(500).json({ message: error.message });
}
};
I want it to finish waiting for the for loop and push the ids into the array before calling next, that way I can store the Ids in the database!
The root cause of your problem is that, as @jfriend00 says in a comment,
fs.readdir()is a plain callback async function. Therefore, execution proceeds to thethen()containingnext()whilefs.readdir()is still running. As @jfriend00 also mentions, mixingthen()andawaitmakes the code more complex and difficult to write correctly.Here's a version that works. It uses
fs.readdirSync(), which simply returns the array of files, and replacesthen()with await to make the code easier to understand.Output: