I have implemented the following code to parse a CSV via a <input type="file" />
selection:
export async function parse(file: File) {
let content = '';
const reader = new FileReader();
reader.onload = function(e: any) {
content = e.target.result;
};
await reader.readAsText(file);
const result = content.split(/\r\n|\n/);
return result;
}
If I run this code and put a breakpoint on the line where I declare result
, it retrieves the contents of the file successfully. If I do not put any breakpoint, the content is empty. As you can see, I added await
to the line where the reader reads the file as text, but it's still not working.
The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read.
The FileReader. onload property contains an event handler executed when the load event is fired, when content read with readAsArrayBuffer, readAsBinaryString, readAsDataURL or readAsText is available.
The FileReader result property returns the file's contents. This property is only valid after the read operation is complete, and the format of the data depends on which of the methods was used to initiate the read operation.
await
doesn't help here. readAsText()
doesn't return a Promise
.
You need to wrap the whole process in a Promise
:
export function parse(file: File) {
// Always return a Promise
return new Promise((resolve, reject) => {
let content = '';
const reader = new FileReader();
// Wait till complete
reader.onloadend = function(e: any) {
content = e.target.result;
const result = content.split(/\r\n|\n/);
resolve(result);
};
// Make sure to handle error states
reader.onerror = function(e: any) {
reject(e);
};
reader.readAsText(file);
});
}
Here is the JSBin I have tried and it work like a charm.
function parse(file) {
const reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event) {
// The file's text will be printed here
console.log(reader.result)
}
}
Updated:
I write you a Promise version.
async function parse(file) {
const reader = new FileReader();
reader.readAsText(file);
const result = await new Promise((resolve, reject) => {
reader.onload = function(event) {
resolve(reader.result)
}
})
console.log(result)
}
To generalize @zero298's answer a tiny bit, here's the generic Promise-based wrapper around FileReader
-
// get contents of a file as obtained from an html input type=file element
function getFileContents(file) {
return new Promise((resolve, reject) => {
let contents = ""
const reader = new FileReader()
reader.onloadend = function (e) {
contents = e.target.result
resolve(contents)
}
reader.onerror = function (e) {
reject(e)
}
reader.readAsText(file)
})
}
used like so -
async function parse(file) {
const contents = await getFileContents(file)
const result = contents.split(/\r\n|\n/)
return result
}
or in the general case,
async function show(file) {
const contents = await getFileContents(file)
alert(contents)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With