节点serialport堆栈监听器,并没有得到完整的答复使用承诺

我遇到了一个问题,那就是我正在尝试使用的基于承诺的代码并不是每次都得到完整的响应。 我正在使用.on的数据侦听器,但将其更改为.once,因为testing显示每次调用都会堆叠数据侦听器。 但无论如何,我偶尔会得到部分答复。 那么我该如何解决这个问题。 不是堆栈监听器,但每次都得到完整的响应…并使用承诺来实现。

sendPort: function(port, src) { return new Promise((resolve, reject) => { // .once, not stacking but sometimes incomplete responses, .on stacking listener port.once('data', (data) => { resolve(data); // TODO parse data here or maybe after return }); port.once('error', (err) => { reject(err); }); // have same debug in .then after call showing listerner not removed with .on Debug.L1('sendport num data listeners: ', port.listenerCount("data")); port.write(src); }); 

这是调用代码

 com.openPort(port).then(port => { _.pTimeout(3000, com.sendPort(port, NCD.gen(args.cmd))) .then(received => { console.log('complete response: ', NCD.parse(received)); Debug.L1('resolved num data listeners: ', port.listenerCount("data")); }) }) .catch(function(e) { console.log('error: ', e) }); 

这里输出使用.on被调用4次,完整的响应应该是[ 170, 1, 0, 171 ] 170,1,0,171 [ 170, 1, 0, 171 ]

  debug:1 api command array: +0ms [ 170, 3, 254, 175, 0, 90 ] debug:1 sendport num data listeners: +1ms 4 complete response: [ 170 ] debug:1 resolved num data listeners: +2ms 4 

另外一次是[170,1,0],大部分时间我都得到完整的答复。

.once的结果类似,但是监听器没有堆叠。

  debug:1 sendport num data listeners: +0ms 1 complete response: [ 170, 1, 0 ] debug:1 resolved num data listeners: +1ms 0 

思考? 想法? 关于修复,但使用承诺。

我的代码来自我在这里find的想法。 Nodejs映射串行端口写入接收数据

从串口gitter的人们得到了一些帮助,所以发布了一个工作完整的解决scheme,我想出了。 底线是你必须使用。然后你必须知道你要回收多less字节。 在我的情况下,我的设备返回一个前导字节,然后第二个字节告诉有多less字节,然后最后一个字节是校验和。 我写了这样一个可以“插入”他们自己的缓冲区分析器,保持连接块,直到你告诉它不要通过改变一个完成标志为真。

所以sendPort上面就这样结束了,这里的port已经创build并且打开了serialPort , cmd是你作为缓冲区向设备发出的命令, parser是你的设备特有的function,它将以大块的formsparsing返回的缓冲区,直到你说完成为止。

 sendPort: function(port, cmd, parser) { return new Promise((resolve, reject) => { Debug.L2('port and buffer for write', port, cmd) let parse = _.Parse(parser); //create object with response and done fields and reference to attached parser Debug.L1('parse response and done initally, ', parse.response, parse.done); port.on('data', (chunk) => { parse.parser(chunk) // Debug.L1('parsed: ', parse.response) Debug.L1('parse done after parser call:', parse.done); if (parse.done) { resolve(parse.response); parse.reset() // sets .done to false and clears out .response Debug.L1('response and done after resolve/complete, ', parse.response, parse.done); port.reset(); //removes all listners to avoid stacking on next call to sendPort } }); port.on('error', (err) => { reject(err); }); port.write(cmd); }); }, 

Parse对象看起来像这样

 // See sendPort - used with custom parser function to return response and completion flag Parse: function(parser) { let parse = function() {} parse.parser = parser; parse.reset = function reset() { this.response = []; this.done = ''; } parse.reset(); // used here to intialize response and return parse 

}

那么你需要写你自己的parsing器函数,你传入这里let parse = _.Parse(parser); 这是特定于您的设备。 这是一个NCD ProXR中继板。

 parse: function(chunk) { for (var byte of chunk) { this.response.push(byte); Debug.L1('response being built ', this.response) } Debug.L1('current chunck response ', this.response) // api version where first byte is 170, if (this.response[1]) { // second slot is number of bits to follow exlcuding checksum if (this.response.length >= 3 + this.response[1]) { // 3 = 170 + number of bits bit + checksum this.done = true } } }, 

为了避免堆栈“数据”侦听器,当我创build可以调用的端口时,我添加了一个重置​​方法,当我知道已经检索完整的响应时。 我使用removeALLlisteners,因为我不能让单一的工作,这没关系,我知道在任何地方代码中没有其他“数据”监听器。

  let serialport = require('serialport'), createPort: function(sysDevName, opts) { opts = opts || {}; opts.autoOpen = false; // actually open device later Debug.L1(sysDevName, opts); let port = new serialport(sysDevName, opts, (err) => { if (err) { Debug.L1("create error" + err.message); return err; } }) port.reset = function() { this.removeAllListeners("data"); this.removeAllListeners("error"); } return port; 

最后需要注意的是, Parse对象包含一个.reset方法,您可以看到它,并且在完成响应之后调用port.reset 。 您需要这样做,否则完成标志不会变成false,而.response仍然包含前一个, "data"监听器将堆栈。