You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Promise内调用csvtoarray报FileReader无该属性TS2339错误解决方法

报错根因

TS抛出Property 'csvtoarray' does not exist on type 'FileReader'.ts(2339)是因为事件回调里的this指向错误:
addEventListener传入普通function声明的回调时,回调内部的this会自动绑定到触发事件的FileReader实例上,而csvtoarray是你在当前类/组件中自定义的方法,根本不在FileReader的原型链上,自然无法找到。另外原代码漏了返回Promise对象,外部调用时拿不到异步读取结果。

修复方法

推荐写法:用箭头函数继承外层this

箭头函数不会篡改this指向,会直接持有外层readFile执行时的类实例上下文,可直接调用自定义的csvtoarray方法,修正后代码如下:

readFile(reader: FileReader, file: File) {
  const deferredResult = new Promise((resolve) => {
    const loadHandler = () => {
      const content = reader.result?.toString() ?? '';
      if (file.type === "application/json") {
        resolve(content);
      } else if (file.type === "text/csv") {
        resolve(this.csvtoarray(content));
      }
      reader.removeEventListener('load', loadHandler);
    }
    reader.addEventListener('load', loadHandler);
  })
  // 必须返回Promise,否则外部拿不到异步读取结果
  return deferredResult;
}

这里单独把load事件处理函数抽成变量,移除监听时不需要特殊写法,比arguments.callee兼容性更好、逻辑更清晰。

兼容写法:提前缓存外层this引用

如果受环境限制不能用箭头函数,可以在外层先把当前实例的this存到变量中,回调里直接用该变量调用方法:

readFile(reader: FileReader, file: File) {
  // 提前缓存当前类实例的上下文
  const currentInstance = this;
  const deferredResult = new Promise((resolve) => {
    function getResult() {
      const content = reader.result?.toString() ?? '';
      if (file.type === "application/json") {
        resolve(content);
      } else if (file.type === "text/csv") {
        // 用缓存的实例调用转换方法,不会出现this指向问题
        resolve(currentInstance.csvtoarray(content));
      }
      reader.removeEventListener('load', getResult);
    }
    reader.addEventListener('load', getResult);
  })
  return deferredResult;
}
补充优化

给csvtoarray方法补上TS类型定义,同时处理Windows换行符、空行等边界情况,避免运行时异常:

csvtoarray(str: string, delimiter: string = ','): Record<string, string>[] {
  // 统一换行符,过滤首尾空白
  const validContent = str.trim().replace(/\r\n/g, '\n');
  if (!validContent) return [];

  const headerLine = validContent.slice(0, validContent.indexOf('\n'));
  const headers = headerLine.split(delimiter).map(h => h.trim());

  const rowLines = validContent
    .slice(validContent.indexOf('\n') + 1)
    .split('\n')
    .filter(line => line.trim());

  return rowLines.map(row => {
    const values = row.split(delimiter);
    return headers.reduce((rowObj, header, idx) => {
      rowObj[header] = values[idx]?.trim() ?? '';
      return rowObj;
    }, {} as Record<string, string>);
  })
}

内容的提问来源于stack exchange,提问作者harsh panday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:06:26