【问题标题】:How to work with FileReader 'synchronously' in react/redux如何在 react/redux 中“同步”使用 FileReader
【发布时间】:2017-03-05 01:05:08
【问题描述】:

由于它是异步的,我在设计一个在 react/redux 应用程序中使用 FileReader API 的解决方案时遇到了一些麻烦。我做了一些环顾四周,但没有什么对我有用。

我有一个 react 组件,它使用 react-dropzone 来获取文件的内容并稍后处理它的内容。每当使用 dropzone 删除文件时,都会触发回调:

onGuestListDrop = (fileData) => {
    const headers =
      FileParser.read(fileData)
        .getHeaders();
  };

我的内部 API 设计的目的是获取 .csv 或 .xlsx 文件的标题,以便将列名映射到现有系统字段名。我在解析文件内容时没有任何问题,我可以正常工作,问题出在 FileReader.onload 事件上。

我的顶级文件解析器是:

class FileParser {

  constructor(file) {
    this.reader = new FileReader();
    this.init(file[0]);
    return this;
  }

  static read(file) {
    return new FileParser(file);
  }

  init(file) {
    switch (file.type) {
      case 'text/csv':
        this.parser = new CsvParser(this.reader, file);
        break;

      default:
        this.parser = new XlsParser(this.reader, file);
        break;
    }
  }

  getHeaders() {
    return this.parser.getHeaders();
  }
}

CSV 类是:

class CsvParser {

  constructor(reader, file) {
    this.reader = reader;
    this.file = file;
    this.parse();
    return this;
  }

  parse() {
    this.reader.readAsText(this.file, "UTF-8");
    this.reader.onload = function (evt) {
      const { result } = evt.target;
      this.parsedContent = Papa.parse(result);
      console.log(this.parsedContent);
    };
  }

  getHeaders() {
    return this.parsedContent.data[0];
  }
}

现在的问题是,当我尝试通过 getHeaders 方法访问标头时,由于 FileReader 异步工作,我得到了未定义。有没有办法通过一些重构来完成这项工作,或者这是不可能的?

我正在考虑使用 redux 操作,但我不确定如何将解析器类与存储连接。我考虑将一个动作直接传递给解析器类,这样我就可以在 FileReader.onload 事件中触发动作创建者。我认为这可行,但我不确定这是在这种情况下使用 redux 的最佳方法。

【问题讨论】:

  • 你需要使用承诺。

标签: javascript reactjs redux filereader


【解决方案1】:

像这样在CsvParser 中添加延迟模式。

class CsvParser {

 constructor(reader, file) {
  this.reader = reader;
  this.file = file;
  this.deferred = {};
  let promise = new Promise((resolve, reject) => {
   this.deferred.resolve = resolve;
   this.deferred.reject = reject;
  });
  this.deferred.promise = promise;
  this.parse();
  return this;
 }

 parse() {
  this.reader.readAsText(this.file, "UTF-8");
   this.reader.onload = function (evt) {
   const { result } = evt.target;
   this.parsedContent = Papa.parse(result);
   console.log(this.parsedContent);
   this.deferred.resolve(this.parsedContent.data[0])
  };
}

getHeaders() {
 return this.deferred.promise;
}

现在像这样更改您的 onGuestListDrop 方法

onGuestListDrop = (fileData) => {
  let headers = {};
  FileParser.read(fileData).getHeaders().then(function (headers) {
    headers = headers;
  });
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-03
    • 2018-09-29
    • 2019-03-03
    • 2019-07-06
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多