Reputation: 1973
I'm communicating with a controller via Serial port (npm serialport module).
The controller handles multiple elements by their id.
The communication is аsync (I sent a request, and there is an event "serialport .on('data')..." that received the response prom the controller.
I have a web API (GET) that receives an id and send a request to the controller to receive the status of element with the given id.
The problem is that when the API needs to response, i haven't received the data from the controller yet.
I also need to support multiple requests at a time via the API.
How do i manage to respond to every request with its correct response?
Thanks a lot Avi
Upvotes: 1
Views: 600
Reputation: 6377
Put controller code in its own module and use a queue of commands. As you pull the next command make that the 'current command'. Each command has a process() function that handles the data from the serial port and returns a value indicating whether it expects more data or has completed. If a command completes then pull the next command.
Each command has a callback that it calls when it completes which you can use to return the async response.
The following is an untested outline (ES6):
// controller.js
var cmds = [], currentCmd = null;
var stream = null;
class ControllerCommand {
constructor(strm) { this.stream = strm;}
send(data) {this.stream.write(data);}
}
class StatusCmd extends ControllerCmd {
constructor(stream, id, cb) {
super(stream)
this.id = id;
this.cb = cb
}
exec() { this.send(`STATUS ${id}`);}
parse(resp) {
this.status = resp;
this.cb(this.status);
return true;
}
}
function next() {
if (cmds.length > 0) {
currentCmd = cmds.shift();
cmd.exec();
}
}
function add(cmd) {
cmds.push(cmd);
if (cmds.length == 1) next();
}
export function status(id, cb) {
add(new StatusCmd(stream, id, cb));
}
export function init(str) {
stream = str;
stream.on('data', (data) => {
if (currentCmd.parse(data.toString())) {
next();
}
});
}
Upvotes: 1