如何编写一个异步函数来解决“数据”事件发射器触发时的问题

时间:2018-11-12 19:43:44

标签: javascript node.js serial-port node-serialport transform-stream

我正在使用node-serialport与硬件进行通信。它只是编写命令并接收响应。

https://serialport.io/docs/en/api-parsers-overview

以下代码有效:

const port = new SerialPort(path);
const parser = port.pipe(new Readline({ delimiter: '\r', encoding: 'ascii' }));

const requestArray = [];

parser.on('data', (data) => {
  // get first item in array
  const request = requestArray[0];

  // remove first item
  requestArray.shift();

  // resolve promise
  request.promise.resolve(data);
});

export const getFirmwareVersion = async () => {
  let resolvePromise;
  let rejectPromise;

  const promise = new Promise((resolve, reject) => {
    resolvePromise = resolve;
    rejectPromise = reject;
  });

  const title = 'getFirmwareVersion';
  const cmd = 'V\r';

  requestArray.push({
    title,
    cmd,
    promise: {
      resolve: resolvePromise,
      reject: rejectPromise
    }
  });

  await v2Port.write(cmd);

  return promise;
};

然后从我的应用程序(用电子/反应编写)中,我可以调用该函数:

<Button onClick={() => {
  let data = await _api.getFirmwareVersion();
  console.log('done waiting...');
  console.log(data);
}>
  Click Me
</Button>

反正我可以重构此代码以使其更简洁吗?

是否有一种方法可以从async函数中获得Promise,而不必重新创建Promise?

有没有办法利用已经存在的Transform Stream并以某种方式通过管道传递Promise?

我也是异步/等待的新手,并且希望避免使用回调,尤其是在React / Redux方面。

我的目标是为api提供很多这些端点(即getFirmwareVersiongetTemperature等)。因此,我想使代码尽可能简洁。我不希望用户界面对API如何获取数据有任何基础知识。它只需要像其他任何API一样请求它,然后等待响应即可。

2 个答案:

答案 0 :(得分:1)

哦,我想我明白了。解析器不断接收数据。因此,当请求到来时,您等待下一个数据,并在到达时将其发送。我建议您写一个中间类。

赞:

const SerialPort = require('serialport')
const Readline = require('@serialport/parser-readline')
const { EventEmitter } = require('events');

class SerialPortListener extends EventEmitter {
  constructor(path) {
    super();
    this.serialPortPath = path;
  }

  init() {
    this.serialPort = new SerialPort(this.serialPortPath);
    const parser = this.serialPort.pipe(new Readline({ delimiter: '\r', encoding: 'ascii' }));

    parser.on('data', data => this.emit('data', data));
  }
}

然后您可以像这样修改getFirmwareVersion:

const serialPortListener = new SerialPortListener(path);

serialPortListener.init();

export const getFirmwareVersion = () => {
  return new Promise((resolve, reject) => {
    serialPortListener.once('data', async (data) => {
      try {
        const cmd = 'V\r';
        await v2Port.write(cmd);
        resolve(data);
      } catch (ex) {
        reject(ex);
      }
    });
  });
};

答案 1 :(得分:0)

在穆罕默德(Mehmet)的帮助下,我最终得到的是:

var array = [
  [1,2],
  [3,4],
  [5,6]
];
array.flat();
// 1,2,3,4,5,6....