最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - FileReader readAsText() async issues? - Stack Overflow

programmeradmin1浏览0评论

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.

Share Improve this question edited Sep 25, 2024 at 14:24 General Grievance 4,98838 gold badges37 silver badges55 bronze badges asked Jun 25, 2018 at 14:56 mellis481mellis481 4,15812 gold badges76 silver badges129 bronze badges 3
  • Instead of returning the result, you should return a Promise, and resolve it in the onload listener – Seblor Commented Jun 25, 2018 at 14:59
  • await doesn't help here. readAsText() doesn't return a Promise. – zero298 Commented Jun 25, 2018 at 15:00
  • FileReader is not return a promise try loadend event here is MDN – jerry_p Commented Jun 25, 2018 at 15:04
Add a comment  | 

4 Answers 4

Reset to default 23

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)
}

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. Replaces readAsText(). If you want other encodings, you should still use the FileReader.
  • arrayBuffer() - for reading as ArrayBuffer. Replaces readAsArrayBuffer().

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;
}
发布评论

评论列表(0)

  1. 暂无评论