Node returning before callback? - node.js

Sorry if this is due to a misunderstanding of how callbacks work, but I'm new to Node and really need to return useful error messages, but at the moment return a success followed later by the error which is caught:
connectDevice: function (ip) {
var port = 5555;
console.log("Connecting to device " + ip + ":5555")
client.connect(ip, port)
.then(function() {
return false; // wait until no errors confirmed
})
.catch(function(err) {
if (err === null) {
return false;
} else {
if (debug) console.error('Could not connect to device at IP ' + ip, err.stack);
console.log('Could not connect to device');
return true; // return error = true
}
});
},
I'm trying to connect to an android device using adbkit which uses promises, however I can't figure out how to adapt them from examples as there's no parent function.
It's important it waits to confirm a connecion before sending commands however. I get this is because of Node's event driven nature but don't know enough how to properly deal with this situation.
Thanks for any help and patience.

Related

Node.js amqplib - not able to implement the reconnect in case of connection close

I am trying to implement a reconnect mechanism when the connection fails to the rabbitmq queue server.This code is only for consuming messages, Below is my code ( the channel Init function takes care of initialising the consumer and binding to the queue ).
connect() {
let conn = amqp.connect(queueConfig.QUEUE_SERVER_URL + "?heartbeat=60");
return conn;
}
createConnection(){
console.log("Trying to connect amqp");
let self = this;
self.connection = this.connect()
.then(function(connection){
console.log("[AMQP] connected");
connection.on("error",function(err){
if (err.message !== "Connection closing") {
console.error("[AMQP] conn error", err.message);
}
});
connection.on("close", function() {
console.error("[AMQP] reconnecting");
return setTimeout(createConnection, 1000);
});
return connection.createConfirmChannel();
})
.then(self.channelInit);
}
On connection failure I am successfully getting the prompt "[AMQP] reconnecting", but after that queue is not getting reconnected, no other prompts are coming in console log.
Please help.
You have a typo in your method. You need use something like setTimeout(createConnection, 1000); instead of your setTimeout(createConnection(), 1000);

NodeJs/WS: How to throw an error server side handled on client side?

I'm trying to throw and error server side when my websocket has more than 2 connections. I have this nice client-side onerror method but I'm unable to reach that part of my code. I'm using nodeJS and the package ws which has the smallest doc on error handling.
server.js
theWebSocketServer.on('connection', function connection(websocket){
if (theWebSocketServer.clients.length >2) {
// I want to throw the error here and pass it to onerror
console.log('No access allowed', theWebSocketServer.clients.length)
} else {
console.log('happy connection', theWebSocketServer.clients.length)
}
})
client.js
wsConnection.onerror = function(eventInfo) {
alert("There was a connection error!");
console.log("Socket error!", eventInfo);
}
How can I send an error to be handled on the client side JS?
In the docs, I can't find any way to send an error to the client. Since ws is a smallish module for websockets, I think it can be used to send messages between server and client and if you need fancy stuff you need to implement your own protocol (the way how you interpret those messages).
For example, in this case it could be something like this:
Client
wsConnection.onmessage = (m) => {
// You can define errors by checking if the event data contains
// something specific: such as the message starts with "Error"
// or if the property of the object is "error" and so on.
if (m.data.startsWith("Error")) {
alert(m.data)
// This will show in the popup:
// "Error: No access allowed"
} else {
// do something else
}
};
wsConnection.onerror = function(eventInfo) {
/* Handle socket errors – e.g. internet goes down, connection is broken etc. */
}
Server:
theWebSocketServer.on('connection', function connection(websocket){
if (theWebSocketServer.clients.length >2) {
websocket.send("Error: No access allowed", err => {
// Ensure your data was actually sent successfully and then
// Close the connection
websocket.close()
// Just in case your data was not sent because
// of an error, you may be interested so see what happened
if (err) { return console.error(err); }
})
// I want to throw the error here and pass it to onerror
console.log('No access allowed', theWebSocketServer.clients.length)
} else {
console.log('happy connection', theWebSocketServer.clients.length)
}
})

Callback was already calleld with async.parallel function

I am writing a simple port scanner using core net module from Node.js. I am getting a 'Callback was already called' error with my code. Can you spot please where the error is coming from? Below is my code:
const net = require('net')
const async = require('async')
function findPortStatus(host, port, timeout, cb) {
const socket = new net.Socket()
socket.setTimeout(timeout, () => {
// couldn't establish a connection because of timeout
socket.destroy()
return cb(null, null)
})
socket.connect(port, host, () => {
// connection established
return cb(null, port)
})
socket.on('error', (err) => {
// couldn't establish a connection
return cb(null, null)
})
}
const funcs = []
for (let port = 0; port <= 80; port++) {
funcs.push(function(callback) {
findPortStatus('192.30.253.112', port, 4000, (err, port) => {
if (!err) {
return callback(null, port)
}
})
})
}
async.parallel(funcs, (err, ports) => {
if (err) {
console.error(err.message)
} else {
for (let port of ports) {
if (port) {
console.log(port)
}
}
}
})
Not sure if this is related, but you really should pass something to the callback when you call it. null,null isn't very useful for debugging. What I would suggest is timeout events in your context are probably not errors, but they are informative. You could just cb(null, 'timeout') or cb(null, {state: 'timedOut', port: port}) or something to better keep track of what worked and what didn't.
The most likely candidate for your actual error, though, is if your socket emits an error or timeout event after the connect event was already successful. Dropped connection or the like. If all you're looking for is a 'ping'-like functionality (across more than just ICMP obviously), then you should probably close the connection as soon as you get a connect and/or remove the other event listeners as part of the connect listener's handler.
Finally, the node docs suggest you not call socket.connect() directly, unless implementing a custom socket (which it doesn't seem like you are), but to use net.createConnection() instead; not sure that'll help you but it's worth noting.
It looks like the successfully connected sockets are subsequently timing out (which makes sense, as you connect but then do nothing with the connection, so it times out).
If you disconnect from a socket once you have recorded a successful connection, then that should clear up the error.

Using domain with serialport-node

I have the node-serialport library working fine in a happy-path situation, but I'd like to address error handling.
The particular test case I'm addressing at the moment is simply that the serial device isn't plugged in. Ideally, I'd be able to detect that a problem exists, and then just retry after a short delay.
The problem is that I keep getting the following error:
events.js:72
throw er; // Unhandled 'error' event
Error: cannot open /dev/ttyACM0
I would expect something like this, since the device isn't plugged in, but I need to catch it. try/catch obviously doesn't work, since it's asynchronous. So I am trying "domain", which appears to be the recommended way:
function reconnect() {
var d = domain.create();
d.on("error", function(err) {
console.error(err);
setTimeout(reconnect, RETRY_DELAY_MS);
});
d.run(function() {
var gps = new SerialPort("/dev/ttyACM0");
gps.on("open", function() {
console.log("Success!");
});
gps.on("error", function(err) {
console.error(err);
setTimeout(reconnect, RETRY_DELAY_MS);
});
});
}
I would expect this to have the desired effect, but I get the same error as above.
Does anyone see anything that I'm just not getting?
The trick is to provide a callback when instantiating the SerialPort object
var serial = new serialPort("/dev/ttyUSB0", { baudrate : 115200 },
function(error) {
if(error)
{
console.log("INIT ERROR: " + error.message + "\n");
}
});

Waiting for an event in Node.js

I have been playing with Node.js for some time.
I have the following piece of script in my server:
socket.on('auth', function(uid, key) {
client.hgetall(uid, function (err, data) {
console.log(data);
if(key != data['key']) {
socket.disconnect();
}
this.user = data;
});
});
socket.on('loginGame', function(gameId) {
checkAuth();
console.log(user);
if(!games[gameId]) {
games[gameId] = {};
}
games[gameId][uid] = uid;
});
In my client;
socket.on('connect', function(){
socket.emit('auth', 1, 1);
socket.emit('loginGame', 1);
});
When I run this code, loginGame function finishes before auth function as I am doing I/O (using redis). I know this a feature of node.js, but I think I am missing something. How can I overcome this issue as auth function needs to finish before running any function. (I have a couple of more functions which need to run in serial)
I have found a node.js module: https://github.com/creationix/step . However, is this the only option? I think this is something most node.js developer might need. I am not that good at JS either.
What is the best and most elegant way of solving this issue?
Thanks,
Have the server send back an acknowledgement when auth is successful, and send loginGame in the handler for that message.

Resources