I'm working on a section of code where the user inputs an image using a , basically like what is used to change a profile picture. My problem is that when I try to read the file with a FileReader(), the program doesn't circle back to the onloadend before the functions that need the result are called. In fact, it only circles back after my fetch gets a response. I've tried async/await, callbacks as far as I know, and some sketchy roundabout methods, but nothing works so far.
My conversion function looks like this:
async function getB64StringFromFile(fileIn) {
var reader = new FileReader();
reader.onloadend = function () {
return reader.result;
}
if (fileIn && (fileIn.type == "image/jpeg" || fileIn.type == "image/png" && fileIn.size < 1 * Math.pow(2, 20))) {
await reader.readAsDataURL(fileIn);
} else {
console.log("bad");
}
}
My main function looks somewhat like this:
async function updateBook(ev) {
var form = ev.target.closest("form");
var data = new FormData(form);
/*long section of code that is irrelevant to the problem*/
var objectData = Object.fromEntries(data);
//the image as a file -- which already proved to be working
let file = document.querySelector('input[type=file]#imageInput').files[0];
if (file) {
objectData.ImageB64String = await getB64StringFromFile(file);
}
fetch("/inventory/update/", {
method: "POST",
contentType: "application/json; charset=utf-8",
body: JSON.stringify(objectData),
headers: {
"Content-Type": "application/json",
"RequestVerificationToken": csrfToken,
},
}).then((res) => { ... })
}
The big problem here is that the firing order is
- UpdateBook()
- Call getB64StringFromFile()
- Fetch
- Response from controller -- which is bad because it didn't have the Base64String along with it
- Goes back to the onloadend and returns the String
What I would want is
- UpdateBook()
- Call getB64StringFromFile()
- wait for the onloadend to be ready
- Go back to the onloadend and get the result
- Fetch
I would love help, I've been at this for 9 hours. There's probably missing awaits or useless/misplaced ones, but I've tried so many things along the way that I forgot what is right.
Edit: I tried to use the PromiseApi but it still doesn't wait, instead it moves on as before while the promise is qualified as 'pending'.
new code with Promise:
function getB64StringFromFile(fileIn) {
return new Promise(function (fulfilled, rejected) {
var reader = new FileReader();
var string;
reader.onloadend = function () {
string = reader.result;
fulfilled(string);
}
if (fileIn && (fileIn.type == "image/jpeg" || fileIn.type == "image/png" && fileIn.size < 1 * Math.pow(2, 20))) {
reader.readAsDataURL(fileIn);
} else {
console.log("bad");
}
})
}
Maybe I'm not using Promise right, I don't know.