Reputation: 155
This is my Code in my Swal.fire preConfirm:
preConfirm: function () {
var selectedfiles = "";
var file = $('#files')[0].files[0];
if (file) {
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
selectedfiles = evt.target.result;
}
reader.onerror = function (evt) {
selectedfiles = "error reading file";
}
}
var email = $('#email').val();
var header = $('#header').val();
var content = $('#content').val();
return {
'email': email,
'header': header,
'content': content,
'selectedfiles': selectedfiles
};
},
Problem is my return doesnt wait for FileReader, and the selectedfiles
is null.
I tried https://stackoverflow.com/a/17491515/13629479 but it doesnt work, its still null.
Upvotes: 0
Views: 1967
Reputation: 5080
You'll need to use JavaScript promises or callbacks to handle the asynchronous nature of FileReader. The FileReader API is asynchronous, meaning the onload event will be called after the file is read, but you need to ensure your post request is made only after this reading is complete.
$("#goodsImage").change(function (e) {
if ($("#goodsImage").val() == "") {
alert("please choose the image you want to upload");
return;
}
var filepath = $("#goodsImage").val();
var extStart = filepath.lastIndexOf(".");
var ext = filepath.substring(extStart, filepath.length).toUpperCase();
if (ext != ".BMP" && ext != ".PNG" && ext != ".GIF" && ext != ".JPG" && ext != ".JPEG") {
alert("only images could be uploaded");
return;
}
readFile(e.target.files[0])
.then(readerRs => {
if (readerRs) {
$.post("@Url.Action('UploadGoodImage')", { localPath: readerRs
}, function (e) {
if (e) {
$("#ImagePreviewUrl").val(e.data);
} else {
// Handle the error if needed
}
});
}
})
.catch(error => {
console.error("Error reading file:", error);
});
});
function readFile(file) {
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onload = function (evt) {
document.getElementById("hidImageStream").value = evt.target.result;
resolve(evt.target.result);
};
reader.onerror = function (evt) {
reject("File reading failed");
};
reader.readAsText(file);
});
}
Upvotes: 0
Reputation: 8459
How about returning Promise so that Swal can resolve it?
preConfirm: function() {
return new Promise((resolve, reject) => {
var selectedfiles = null;
var email = $('#email').val();
var header = $('#header').val();
var content = $('#content').val();
var file = $('#files')[0].files[0];
if (file) {
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
resolve({
'email': email,
'header': header,
'content': content,
'selectedfiles': evt.target.result
});
}
reader.onerror = function (evt) {
reject("error reading file");
}
} else {
resolve({
'email': email,
'header': header,
'content': content,
'selectedfiles': null
});
}
});
}
Upvotes: 2
Reputation: 1074208
According to the documentation, you can return a promise to make it wait for something asynchronous. So you could do something like this (since async
functions return promises):
preConfirm: async function () {
const file = $('#files')[0].files[0];
// The `text` method returns a promise for the text of the file
const selectedfiles = file ? await file.text() : "";
const email = $('#email').val();
const header = $('#header').val();
const content = $('#content').val();
return {
email,
header,
content,
selectedfiles,
};
},
You could use FileReader
instead wrapping it in a promise, but the File
object's text
method (inherited from Blob
) is more convenient.
Upvotes: 3