求助:Uncaught TypeError: Cannot read property 'open' of undefined错误排查
解决Cannot read property 'open' of undefined的问题
嘿,我帮你排查了下代码,这个错误主要来自两个关键问题,咱们一步步来解决:
1. 构造函数里调用find()的时机错了
你看你的Sensors构造函数,先调用了this.find(),然后才去创建this.port对象。这就导致当find()执行的时候,this.port还没被赋值,完全是undefined,自然调用this.port.open()就报错了。
修正方法:把this.find()移到this.port初始化之后:
function Sensors(com) { this.address = com; // 先初始化port对象 this.port = new sp(com, { baudrate: 9600, autoOpen: false }); // 再调用find方法 this.find(); }
2. 回调函数里的this指向混乱
在find方法的各种回调(比如open的回调、data事件的回调)里,默认的this并不是你的Sensors实例——普通函数回调里的this会指向调用它的上下文,比如port.open的回调里this是port对象,而data事件的回调里this可能是全局的window对象。这会导致后续你想访问this.port的时候出问题。
解决办法有两种,选你顺手的就行:
方法一:用箭头函数(最推荐)
箭头函数会继承外层作用域的this,也就是你的Sensors实例,这样就不会乱了:
Sensors.prototype.find = function() { console.log("ran"); this.port.open((err) => { if (err) { return console.log('Error opening port: ', err.message); } this.port.write('i' + String.fromCharCode(13), (err) => { if (err) { return console.log('Error on write: ', err.message); } console.log('message written'); }); this.port.on('data', (data) => { var sensorData = data; var splitString = sensorData.toString().split(','); console.log(splitString[1]); if (sensorData.length > 0) { if (splitString[1] === 'pH' || splitString[1] === 'EC' || splitString[1] === 'RTD') { console.log(splitString[1]); } this.port.close((err) => { console.log('port closed', err); }); } }); }); };
方法二:提前把this存成变量
在find方法开头把实例的this存到一个变量(比如self),然后所有回调里都用self代替this:
Sensors.prototype.find = function() { console.log("ran"); const self = this; // 保存当前实例的引用 self.port.open(function(err) { if (err) { return console.log('Error opening port: ', err.message); } self.port.write('i' + String.fromCharCode(13), function(err) { if (err) { return console.log('Error on write: ', err.message); } console.log('message written'); }); self.port.on('data', function(data) { var sensorData = data; var splitString = sensorData.toString().split(','); console.log(splitString[1]); if (sensorData.length > 0) { if (splitString[1] === 'pH' || splitString[1] === 'EC' || splitString[1] === 'RTD') { console.log(splitString[1]); } self.port.close(function(err) { console.log('port closed', err); }); } }); }); };
3. 额外的小坑:重复调用find()
在findSensors函数里,你创建sensor实例之后又调用了一次sensor.find(),但其实构造函数里已经调用过find()了,这会导致端口被重复打开,建议把这行重复的调用删掉。另外这里建议用let声明循环变量i,避免全局变量污染:
function findSensors() { sp.list(function(err, ports) { for (let i = 0; i < ports.length; i++) { var sensor = new Sensors(ports[i].comName); // 删掉下面这行,构造函数里已经调用过find()了 // sensor.find(); } }); }
把这些修改做完,你的代码应该就能正常运行,不会再出现那个错误啦!
内容的提问来源于stack exchange,提问作者dottedquad
相关产品推荐
相关产品推荐

