I am trying to build a webserver with sailsjs.
In order to perform its request, my server needs to connect to a socket to pass commands and wait for reponses.
For each command, I wait for a specific response and have to call a specific callback. Currently I only open one socket and change the "onData" socket at each request. It looks like it does not work well and is ugly.
Another option could be to open and close a socket for each command or request : I find it even worst.
Is there a clever way to do what I need ?
Edited:
Here is the socket (DriverConnection.js):
module.exports = {
connect: function(callback){
var net = require('net');
client = net.connect({port: 13}, function() { //'connect' listener
console.log('client connected');
callback();
});
},
command: function(command, callback){
client.write(command);
client.on('data', function(data) {
console.log("parsing data " + data.toString());
callback(JSON.parse(data.toString()));
});
}
};
Here is a example of its request usage :
module.exports = {
list: function(req,res) {
DriverConnection.command('{}',function(data){
for(key in data) {
var mac = data[key];
Autoreez.findOne({name : mac},function (err,auto){
if(!auto) {
User.create({name : mac}, function(err,user){
res.send(user);
});
} else {
res.send(auto);
}
});
}
});
},
}
One possible solution is to create response router which fire specific callback depending on request name.
As the net module doesn't support such behaviour natively, you'll need to use some kind of library or write your own router using (for example) EventEmitter.
Step 1
Create Driver service: api/services/DriverService.js
var net = require('net');
module.exports = {
connection: null,
// open connection
connect: function(cb) {
var self = this;
this.connection = net.connect({ port: 13 }, cb);
// response router
this.connection.on('data', function(data) {
var res = JSON.parse(data.toString());
self.connection.emit(res.req, res.msg);
});
},
// close connection
disconnect: function() {
this.connection.end();
},
command: function(cmd) {
this.connection.write(cmd);
// return an instance of event emitter
return this.connection;
}
};
Step 2
Next, connect to your socket server when sails application starts and disconnect when it stops.
// config/bootstrap.js
module.exports.bootstrap = function(cb) {
// connect to service
DriverService.connect(cb);
};
// config/teardown.js
module.exports.beforeShutdown = function(cb) {
// disconnect from service
DriverService.disconnect();
cb();
};
Step 3
Modify your socket server to send response with request name.
// ...
socket.on('data', function (data) {
var reqName = data.toString();
socket.write(JSON.stringify({ req: reqName, msg: 'some response' }));
});
// ...
Step 4
Now, you can bind any any kind of callback to specific request.
If you prefer, you can bind them inside the DriverService (in connect() function) or dynamically in your application controller, as follows:
api/services/DriverService.js
this.connection
.on('data', function(data) {
var res = JSON.parse(data.toString());
self.connection.emit(res.req, res.msg);
})
.on('list', function(data) { /* ... */ })
.on('add', function(data) { /* ... */ })
OR
api/controllers/SomeController.js
module.exports = {
list: function(req, res) {
DriverService.command('list')
.once('list', function(data) {
console.log('callback for list request');
res.send(data);
})
.once('add', function(data) {
console.log('callback for add request');
res.send(data);
});
}
}
in case of binding in controller, once() must be used to prevent binding multiple event listeners.
Hope that helps.