JS调用类方法报Cannot read property 'myArray' of undefined错误求解
错误原因分析
报错的核心原因是this指向丢失:
你最后一行写的myString.then(myObj.myFunction)是直接把myFunction方法本身作为回调传给Promise的then方法,当回调执行时,myFunction内部的this已经脱离了myObj实例绑定,严格模式下this默认是undefined,所以访问this.myArray就会抛出找不到属性的错误。
解决方法有两种:
- 用箭头函数包裹调用:
myString.then(res => myObj.myFunction(res)),箭头函数会继承外层的上下文,保证myFunction执行时this指向myObj实例,同时还能拿到myStringresolve出来的字符串值。 - 用bind方法手动绑定this:
myString.then(myObj.myFunction.bind(myObj)),强制把myFunction的执行上下文绑定到myObj实例上。
其他代码问题梳理
你的代码里还存在多处语法和逻辑错误,也会导致后续运行失败:
- 你给
fs.createReadStream传的是字符串'filename',不是构造函数接收的filename参数,永远读不到你传入的myCSV.csv文件,需要去掉引号改成fs.createReadStream(filename)。 - 你原来的CSV读取逻辑中,Promise从未被resolve,且data事件返回的data没有被存入数组,读到的CSV数据会全部丢失。同时
myArray里存的是Promise对象,不是你要的CSV行数据,访问this.myArray[i]['phrase']根本拿不到对应值。 - JS里布尔值是小写的
true/false,你写的大写True/False会报未定义错误。 datetime、divmod都是Python的语法,JS原生没有这两个API,需要用JS的Date对象实现对应的时间计算逻辑。myString本身是Promise对象,不能直接调用includes方法,要先拿到它resolve后的值再做判断。
CSV读取逻辑优化方案
你可以把CSV读取封装成独立的异步方法,等所有行读取完成后再把数据存入myArray,参考实现如下:
const fs = require('fs'); const csv = require('csv-parser') const myString = new Promise((resolve, reject) => { resolve('John'); }); class myClass{ constructor(filename){ this.myArray = []; this.filename = filename; } // 封装CSV读取方法,返回Promise方便后续等待加载完成 async loadCSV() { return new Promise((resolve, reject) => { const results = []; fs.createReadStream(this.filename) .pipe(csv(['FirstName', 'LastName', 'Address', 'Town', 'Country', 'Postcode'])) .on('data', (data) => results.push(data)) .on('end', () => { this.myArray = results; resolve(); }) .on('error', reject) }) } async myFunction(targetStr) { for(let i = 0; i < this.myArray.length; i++) { if (targetStr.includes(this.myArray[i]['FirstName'])){ if (this.cooled_down(i)){ this.approve(i, targetStr); } } } } cooled_down(i){ const item = this.myArray[i] if (!item.hasOwnProperty('approved')){ // 从未审批过直接返回true return true; } else{ const now = Date.now(); const duration = now - item.approved; const hours = duration / (1000 * 3600); if (hours >= 24){ return true; } else{ console.log("Couldn't approve " + item['FirstName'] + " Cool Down time: " + (24 - Math.floor(hours)) + "小时"); return false; } } } approve(i, targetStr){ const item = this.myArray[i]; try{ setTimeout(() => { console.log(targetStr); console.log(item['FirstName']) console.log(item['Postcode']) }, 60 * 60 * 3 * 1000); }catch(e){ console.log(e); } this.myArray[i]['approved'] = Date.now(); } } // 调用逻辑:先加载CSV,再获取字符串值,最后执行你的业务逻辑 const myObj = new myClass("myCSV.csv"); (async () => { await myObj.loadCSV(); const targetStr = await myString; await myObj.myFunction(targetStr); })().catch(err => console.error(err))
内容的提问来源于stack exchange,提问作者DavidNyan10
相关产品推荐
相关产品推荐

