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.
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.
4 Answers
Reset to default 23await
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)
}
You don't have to use FileReader
anymore if you have a File
, and you just want to read the contents as UTF-8 text or raw data. (Some extra work will have to be done for readAsDataURL()
, however.) File
inherits from Blob
, which means you have the Promise-based methods available to you:
text()
- for reading file as UTF-8 text. ReplacesreadAsText()
. If you want other encodings, you should still use theFileReader
.arrayBuffer()
- for reading asArrayBuffer
. ReplacesreadAsArrayBuffer()
.
These are supported on all major browsers, according to MDN, as of 2021.
The function in the question can now just be written:
export async function parse(file: File) {
const content = await file.text();
const result = content.split(/\r\n|\n/);
return result;
}
onload
listener – Seblor Commented Jun 25, 2018 at 14:59await
doesn't help here.readAsText()
doesn't return aPromise
. – zero298 Commented Jun 25, 2018 at 15:00