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.
Related
I have about 50-60 outbound calls to make once an hour. I have a Serverless function calling a flow API. The flow api calls a Function. And the function looks like this:
const makeCalls = (arr, callbackHandler) => {
const client = context.getTwilioClient();
let itemsProcessed = 0;
arr.forEach(item => {
client.calls.create({
url: 'https://channels.autopilot.twilio.com/v1/XXX/XXX/twilio-voice',
to: item.phone,
from: 'XXX',
}, function(err, result) {
itemsProcessed++;
if (err) { console.error(err); return; }
console.log('New phone call started...', result);
});
});
if(itemsProcessed === arr.length) { callbackHandler(); }
};
Every time I execute the script, the phone calls go out just fine, but I get a runtime application timed out error. How do I fix the issue? What am I missing? (I apologize for the janky async handling).
I figured it out. I put my janky async test in the wrong place. It should have been in the function call that returns the result.
I'm wondering if this is the correct way of doing recursive setTimeout in Node.js?
module.exports = {
connect: function(callback) {
amqp.connect(config.queue.url, function(err, connection) {
if (err) {
console.error("[AMQP]", err.message);
return setTimeout(module.exports.connect, 1000); // keep reconnecting
}
});
}
}
I'm trying to implement a reconnecting mechanism in Node.js. But I'm not sure if this line is going to have a side effect in JavaScript? return setTimeout(module.exports.connect, 1000);
It should work fine but i think you should improve your code to allow notification of the caller of the connection attempt (even if you perform reconnection).
I am trying to prototype a load testing scenario on socket interactions using Mocha and should.js. I have an array of user details which I want to authenticate using socket communication and wish to verify their responses. It works fine for a single user, however when I try to loop for multiple users - I end up with issues. Had gathered some inputs based on the post:Tests from looping through async JavaScript (Mocha) .
Below is the code snippet:
var users = [{name:'A',password:'password',expected:'success'},{name:'B',password:'badPass',expected:'failure'}];
describe('socket Interaction test' , function() {
function socketInteraction(users, done) {
client.emit('userAuthentication', {'name':users.name,'password':users.password}, function(callback) {
console.log('Emit' + users.name);
});
client.on('userAuthenticationResponse', function(response) {
console.log('Resp' + response.status + 'Expected' + users.expected);
response.status.should.equal(users.expected);
done();
});
}
it('Dummy', function(done) {
describe('Mutiple login Test Async', function() {
it('User Login Test', function(done) {
users.forEach(function(users, callback) {
console.log(users.name);
socketInteraction(users, function(err) {
if (err) {
return;
}
done();
});
});
});
});
});
});
The response I get upon running the test is:
socket Interaction test
✓ Dummy
Mutiple login Test Async
A
B
RespsuccessExpectedsuccess
✓ User Login Test
RespsuccessExpectedfailure
2 passing (43ms)
The second test has to fail. Not sure where I have messed up the code. Appreciate some pointers to fix this. Thanks.
The done Parma should be called in the second param of the async.forEach. The done you call in the loop function should be callback(), to tell async that just that user is finished.
You don't have the async finished callback yet at all.
Would have posted code but am on my phone. I can add later if it's not clear.
I don't even know if that question makes sense. I don't have a lot of experience with socket.io or deployd. You'll probably understand what I'm trying to do from my code. It's similar to this. Here is my server code.
var deployd = require('deployd');
var options = {
//options go here
};
var dpd = deployd(options);
dpd.listen();
dpd.on('getLobby', function (lobby) {
dpd.lobby = lobby; //trying to bind variable to socket
console.log('get Lobby');
});
dpd.on('disconnect', function() {
console.log("disconnected");
});
dpd.on('connection', function (socket) {
console.log('connection');
});
and on my client side I have this
dpd.socket.emit('getLobby', lobby, function (data) {
console.log("emitted");
console.log(data);
});
The server works. My app works. Everything runs fine except for this code. I get no errors and no console logs. None of this code seems to work at all. It doesn't seem to emit and it doesn't seem to catch an emission if there even is one. I have tried lots of different ways of writing this.
I am using Node.js with Express and have code similar to this as part of my routes:
requireLogin: function(req, res, next) {
User.find(req.session.userId)
.on('success', function(user) {
req.addListener('data', function(chunk) {
console.log("DATA: " + chunk);
}
next()
}
}
I am using Sequelize and the User.find method is accessing the database. The trouble is, the request 'data' event that I bind to is never fired. It seems that the data event had already been triggered and handled by the time the user is returned from the database and it's too late to do anything with it. In the example above I could just move the req.addListener to outside the database callback, but in reality I am calling next() here which can't be moved.
All of the following route middleware that is called by next() then doesn't have access to the request data since these events have already been fired. Worse than that, they just hang waiting for the data event from req because it has already happened.
How can I somehow delay the data event so that it can be bound to from within the database callback? Or have I misunderstood something fundamental and need to change my way of going about this?
Thanks a lot.
Edit: I found a relevant discussion in the nodejs Google group which suggests there isn't a solution that will work for me.
var cache = new function () {
var arr = [],
cbs = [];
this.add = function(data) {
arr.push(data);
cbs.forEach(function(cb) {
cb(arr);
});
}
this.get = function(cb) {
cbs.push(arr);
if (arr.length > 0) {
cb(arr);
}
}
};
req.addListener('data', function(chunk) {
cache.add(chunk);
};
User.find(
req.session.userId
).on('success', function(user) {
cache.get(function(data) {
// stuff
next();
});
};
I presume what you actually want is some kind of message caching. Now this is a vague proof of concept. What you actually want depends on your code.
If you have any kind of deferred library / abstraction available then the code will become a lot smaller.