How do I properly encapsulate a socket.io socket? - javascript

This code is running in my node.js server application:
io.sockets.on('connection', function (socket) {
var c = new Client(socket, Tools.GenerateID());
waitingClients.push(c);
allClients.push(c);
if (waitingClients.length === 2)
{
activeGames.push(new Game([waitingClients.pop(), waitingClients.pop()]));
}
});
function Client(socket, id)
{
this.Socket = socket;
this.ID = id;
this.Player = new Player();
this.Update = function(supply)
{
socket.emit('update', { Actions: this.Player.Actions, Buys: this.Player.Buys, Coins: this.Player.Coins, Hand: this.Player.Hand, Phase: this.Player.Phase, Supply: supply});
}
socket.on('play', function(data) {
console.log(data);
console.log(this.Player);
});
socket.emit('id', id);
}
The part I'm having trouble with is the event handler for the 'play' event. console.log(this.Player) outputs undefined. I sorta understand why it's wrong, because 'this' refers to something other than my client object (the socket? the anonymous function?) , but I don't know how to re-arrange the code to handle the 'play' event properly, and have full access to the members of the Client object.

You just need to store this in some other variable inside Client.
function Client(socket, id)
{
var self = this;
...
socket.on('play', function(data) {
self.Player.play();
});

Related

node js self this call method

I'm working on NodeJS and I have this module:
Manager.js
with this code (this is not all the code...):
//
// Object Manager
function Manager(params) {
client = new ModbusRTU();
}
//connessione alla seriale per lettura modbus
Manager.prototype.connectClient = function(){
// try to connect
client.connectRTUBuffered ("/dev/ttyS3", { baudRate: 19200 })
.then(function()
{
mbsState = MBS_STATE_GOOD_CONNECT;
mbsStatus = "Connected, wait for reading...";
console.log(mbsStatus);
})
.catch(function(e)
{
mbsState = MBS_STATE_FAIL_CONNECT;
mbsStatus = e.message;
console.log("Error:"+e);
});
client.setTimeout (20);
}
//read data
Manager.prototype.readData = function(){
var self = this;
client.setID(2);
// try to read data
client.readCoils (0, 7, function(error,data){
if(!error){
self.checkEmergency();
}
});
}
//emergency
Manager.prototype.checkEmergency= function(){
}
exports.Manager=Manager;
client part of code is about a modbus application.
When I try to call "self.checkEmergency()" from readData, I have this error:
"self.checkEmergency() is not a function"
Why?
The method readData is called inside a method like this:
Manager.prototype.caller= function(){
var self = this;
self.readData();
}
I also have used self to pass the object to the callback...
Any idea?

JavaScript WebSocket replace reference with new socket

I'm trying to reconnect a websocket automatically with a function.
I want it to keep the same variable name, but i'm having some issues.
here is the function I'm using
function reconnect(obj){
try{
obj=new WebSocket(obj.url);
}
except{
setTimeout(reconnect,5000,obj);
}
}
mysocket=new Websocket(myurl);
mysocket.close()
reconnect(mysocket)
After the reconnect function runs successfully but mysocket is still referenced to the old closed Websocket. I'm not sure how to transfer to new Websocket object to the old variable.
You are overriding the variable. There are multiple ways to do it, quickest would be to pass an object.
function reconnect(obj){
var mySocket = obj.mySocket;
try {
obj.mySocket=new WebSocket(mySocket.url);
}
except {
setTimeout(reconnect, 5000, obj);
}
}
mysocket=new Websocket(myurl);
mysocket.close()
var wrapperObject = {mysocket};
reconnect(wrapperObject);
// At any point of time `wrapperObject.mysocket` will have the latest socket instance
A more cleaner approach would be to define a wrapper class/function which scopes the mySocket variable privately. EX:
function ReconnectSocket (mySocket) {
this.mySocket = mySocket
}
ReconnectSocket.prototype.reconnect = function () {
try {
this.mySocket = new WebSocket(this.mySocket.url);
}
except {
setTimeout(reconnect, 5000);
}
}
ReconnectSocket.prototype.getSocket = function () {
return this.mySocket
}
var mysocket=new Websocket(myurl);
mysocket.close()
var reconnectSocket = new ReconnectSocket(mysocket).reconnect()
// `reconnectSocket.getSocket()` will give the latest instance at any point of time
First approach is using global variable
function reconnect(){
try{
mysocket=new WebSocket(mysocket.url);
}
except{
setTimeout(reconnect,5000);
}
}
mysocket=new Websocket(myurl);
mysocket.close()
reconnect()
Second approach, I think you should wrap your socket in a object
function reconnect(obj){
try{
obj.mysocket=new WebSocket(obj.mysocket.url);
}
except{
setTimeout(reconnect,5000,obj);
}
}
var socketObject = {};
socketObject.mysocket=new Websocket(myurl);
socketObject.mysocket.close()
reconnect(socketObject)

Replace attributes of a document in publish function

I'm using meteor and I have a question about the publish function (server side)
Meteor.publish('users', function () { .... }
I'm sending now documents to the browser which have id's of other collections. For example the Task document belongs to a project
{
title: '....',
projectId: 'KjbJHvJCHTCJGVY234',
...
}
What I want is to add a property to the this document projectTitle so I don't have to look up the project on the client. However, when I add this property in the publish function it is not send to the client. This is what I've tried:
Meteor.publish('tasks', function () {
var tasks = Tasks.find();
tasks.forEach(function (task) {
var project = Projects.findOne({_id: task.projectId});
task.projectTitle = project.title;
});
return tasks;
}
Any suggestions how to modify documents (not persistent) inside the publish function?
You could do this:
Meteor.publish("tasks", function() {
var transform = function(task) {
var project = Projects.findOne({_id: task.projectId});
task.projectTitle = project.title;
return task;
}
var self = this;
var tasks = Tasks.find().observe({
added: function (document) {
self.added('tasks', document._id, transform(document));
},
changed: function (newDocument, oldDocument) {
self.changed('tasks', document._id, transform(newDocument));
},
removed: function (oldDocument) {
self.removed('tasks', oldDocument._id);
}
});
self.ready();
self.onStop(function () {
tasks.stop();
});
});
There's a lot of custom logic there, but the 'transform' basically adds the attributes in.
Your code looks good but you're forgetting the .fetch() method on your task request. It should be var tasks = Tasks.find().fetch();

Start object from setInterval?

I have the following reconnect method for Sockjs which almost is fully working:
(function() {
// Initialize the socket & handlers
var connectToServer = function() {
var warbleSocket = new SockJS('http://url.com:5555/warble');
warbleSocket.onopen = function() {
clearInterval(connectRetry);
$('.connect-status')
.removeClass('disconnected')
.addClass('connected')
.text('Connected');
};
warbleSocket.onmessage = function(e) {
$('#warble-msg').text(e.data);
};
warbleSocket.onclose = function() {
clearInterval(connectRetry);
connectRetry = setInterval(connectToServer, 1000);
$('.connect-status')
.removeClass('connected')
.addClass('disconnected')
.text('Disconnected');
};
// Connect the text field to the socket
$('.msg-sender').off('input').on('input', function() {
warbleSocket.send($('.msg-sender input').val());
});
function send(a) {
warbleSocket.send(a);
}
return {
send: send
};
}();
var connectRetry = setInterval(connectToServer, 1000);
})();
The error i am getting is when its trying to reconnect.
Error is:
SyntaxError: missing ] after element list
at this line:
connectRetry = setInterval(connectToServer, 1000);
Any ideas what im doing wrong here?
Your connectToServer variable is not a function, it's an object with a property send that is a function, so it doesn't make sense to say setInterval(connectToServer, 1000). Try this instead:
setInterval(connectToServer.send, 1000);
Why don't you simplify things a bit?
I would put connection stuff inside a specific function and call it from setInterval().
Something like this (use with care since I'm not testing this code, ok?):
(function() {
// Initialize the socket & handlers
var connectToServer = function() {
var warbleSocket;
function connect() {
warbleSocket = new SockJS('http://url.com:5555/warble');
warbleSocket.onopen = function() {
// ...
};
warbleSocket.onmessage = function(e) {
// ...
};
warbleSocket.onclose = function() {
// ...
}
// Connect the text field to the socket
$('.msg-sender').off('input').on('input', function() {
warbleSocket.send($('.msg-sender input').val());
});
function send(a) {
warbleSocket.send(a);
}
return {
send: send
};
}();
// you probably will need to call the first connection
connectToServer();
// and than set connection retry
var connectRetry = setInterval(connectToServer.connect, 1000);
})();
I hope it helps you.
Regards,
Heleno

Getting Error while creating Signal R Hubs

I am getting below java script error when i am using signalR for creating Hubs Dynamically. I am using "jquery.signalR-1.1.2.js" .
"Microsoft JScript runtime error: Object doesn't support property or method 'sending'"
Below is the Javascript code that is generated automatically.
signalR.hub = signalR("/signalr")
.starting(function () {
updateClientMembers(signalR);
})
.sending(function () {
var localHubs = [];
$.each(hubs, function (key) {
var methods = [];
$.each(this, function (key) {
if (key === "obj") {
return true;
}
methods.push(key);
});
localHubs.push({ name: key, methods: methods });
});
this.data = window.JSON.stringify(localHubs);
})
There is no sending on the default SignalR connection object, that's what the error is telling you. What is it you're trying to do??

Categories

Resources