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
相关产品推荐
相关产品推荐

