Can't access variable in custom Node.js module - javascript

I am trying to have a module contain the information for different roles for a game but whenever I try and receive the data from the variables I create, it comes as undefined and/or I get errors saying something similar to saying the variable inside the data doesn't exist (such as the role's name).
I've seen a bunch of tutorials do similar but I can't seem to figure out what I've done wrong.
My index file.
var express = require('express');
var app = express();
var serv = require('http').Server(app);
var RoleList = require('./_modules/RoleList');
var Socket = function() {}
Socket.list = {};
serv.listen(process.env.PORT || 4567);
console.log("Server started.");
var io = require('socket.io')(serv, {});
io.sockets.on('connection', function(socket) {
socket.id = Math.random();
Socket.list[socket.id] = socket;
console.log('Player Connected');
console.log('Role Name: ' + RoleList.testRole.roleName);
socket.on('disconnect', function() {
delete Socket.list[socket.id];
console.log('Player Disconnected');
});
});
RoleList Module
var Role = function() {
var self = {};
var roleName = 'TestingRoleName';
return self;
}
modules.exports = {
roleTest: Role
}
But upon running the server I get the results.
Server started.
Player Connected
T:undefined
instead of
T:TestingRoleName
Is anyone able to help with this? I'd appreciate that so much :D I am likely doing something completely wrong but I can't seem to find an answer anywhere.

This i because Role is a function not Object. You need to call function to return self. And you should set roleName as property of self
var Role = (function() {
var self = {};
self.roleName = 'TestingRoleName';
return self;
})();
Or you can change Role to this.This is the way I recommend
var Role = {
roleName:'TestingRoleName'
}

Related

node.js call ws.send from controller

i want to send a websocket, using express-ws out from a different controller, not by route and I have the following code in the server.js:
var SocketController = require('./routes/ws.routes');
var app = express();
var server = require('http').createServer(app);
var expressWs = require('express-ws')(app);
app.ws('/', SocketController.socketFunction);
the SocketController looks like that:
exports.socketFunction = function (ws, req) {
ws.on('message', function(msg) {
console.log(msg);
ws.send("hello");
});
}
Is it possible to call the
ws.send()
event from another controller? How do i get the "ws" object?
thanks!
You will have to store your sockets in memory. To access stored sockets from different modules, you can store references for these sockets in a separate module.
For example, you can create a module socketCollection that stores all the active sockets.
socketCollection.js:
exports.socketCollection = [];
You can import this module where you define your web socket server:
var socketCollection = require('./socketCollection');
var SocketController = require('./routes/ws.routes');
var app = express();
var server = require('http').createServer(app);
var expressWs = require('express-ws')(app);
expressWs.getWss().on('connection', function(ws) {
socketCollection.push({
id: 'someRandomSocketId',
socket: ws,
});
});
app.ws('/', SocketController.socketFunction);
Now every time new client connects to the server, it's reference will be saved to 'socketCollection'
You can access these clients from any module by importing this array
var socketCollection = require('./socketCollection');
var ws = findSocket('someRandomSocketId', socketCollection);
var findSocket = function(id, socketCollection) {
var result = socketCollection.filter(function(x){return x.id == id;} );
return result ? result[0].socket : null;
};

Use JSON Object for Function Pointer Mapping in NodeJS

I'm trying to learn Socket.io and I'm a beginner in NodeJS.
I'm using JSON object as a kind of key-value store for mapping callback function with relevant event names. May be there is some other alternative to do it efficiently which I don't know. The problem is in the code below, when I call bob.printName() it prints the JSON object perfectly. But when I call the same function using the callbacks['connection'](), it says the JSON object is undefined. I would like to know the reason of that and also love to know any other efficient alternatives like PHP like array indexing.
/***
** index.js
***/
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var User = require('./User');
var bob = new User();
var callbacks = {
'connection': bob.printName
};
io.on('connection', function(socket){
bob.printName();
callbacks['connection']();
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
/***
** User.js
***/
var jsonObj = null;
function User() {
this.jsonObj = {
type: 'type',
body: 'body'
};
}
User.prototype.printName = function(){
console.log(this.jsonObj);
}
module.exports = User;

node.js eventListener not listen

i'm a noob of node.js and i'm following the examples on "Node.js in action".
I've a question about one example :
The following code implements a simple chat server via telnet. When i write a message, the script should send message to all connected client.
var events = require('events');
var net = require('net');
var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join',function(id,client){
this.clients[id] = client;
this.subscriptions[id] = function(senderId,message){
if(id != senderId){
this.clients[id].write(message);
}
};
this.on('broadcast',this.subscriptions);
});
var server = net.createServer(function(client){
var id = client.remoteAddress+':'+client.remotePort;
client.on('connect',function(){
channel.emit('join',id,client);
});
client.on('data',function(data){
data = data.toString();
channel.emit('broadcast',id,data);
});
});
server.listen(8888);
But when i try to connect via telnet and send a message it doesn't work.
Thanks
A couple issues I noticed. See the comments in the code.
var events = require('events');
var net = require('net');
var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join',function(id, client) {
this.clients[id] = client;
this.subscriptions[id] = function(senderId,message) {
if(id != senderId)
this.clients[id].write(message);
};
//added [id] to "this.subscriptions"
//Before you were passing in the object this.subscriptions
//which is not a function. So that would have actually thrown an exception.
this.on('broadcast',this.subscriptions[id]);
});
var server = net.createServer(function(client) {
//This function is called whenever a client connects.
//So there is no "connect" event on the client object.
var id = client.remoteAddress+':'+client.remotePort;
channel.emit('join', id, client);
client.on('data',function(data) {
data = data.toString();
channel.emit('broadcast',id,data);
});
});
server.listen(8888);
Also note: If a client disconnects and another client sends a message then this.clients[id].write(message); will throw an exception. This is because, as of now, you're not listening for the disconnect event and removing clients which are no longer connected. So you'll attempt to write to a client which is no longer connected which will throw an exception. I assume you just haven't gotten there yet, but I wanted to mention it.

How to pass data to Mongodb using Node.js, websocket and total.js

I am trying to pass data to Mongodb using Websocket and total.js.
In my homepage.html I can get the user input and connect to the server via websocket after clicking the save button.
In default.js is my server side code. At this point the app hat got the user input and connected to the server correctly, but how can I save data to mongodb now?
This is my homepage.html
<br />
<div>
<input type="text" name="message" placeholder="Service" maxlength="200" style="width:500px" />
<button name="send" >Save</div>
</div>
<br />
<script type="text/javascript">
var socket = null;
$(document).ready(function() {
connect();
$('button').bind('click', function() {
if (this.name === 'send') {
console.log(send());
return;
}
});
});
function connect() {
if (socket !== null)
return;
socket = new WebSocket('ws://127.0.0.1:8000/');
socket.onopen = function() {
console.log('open');
};
socket.onmessage = function(e) {
var el = $('#output');
var m = JSON.parse(decodeURIComponent(e.data)).message;
el.val(m + '\n' + el.val());
};
socket.onclose = function(e) {
// e.reason ==> total.js client.close('reason message');
console.log('close');
};
}
function send() {
var el = $('input[name="message"]');
var msg = el.val();
if (socket !== null && msg.length > 0)
socket.send(encodeURIComponent(JSON.stringify({ message: msg })));
el.val('');
return msg;
}
This is my default.js
exports.install = function(framework) {
framework.route('/', view_homepage);
framework.route('/usage/', view_usage);
framework.websocket('/', socket_homepage, ['json']);
};
function view_usage() {
var self = this;
self.plain(self.framework.usage(true));
}
function view_homepage() {
var self = this;
self.view('homepage');
}
function socket_homepage() {
var controller = this;
controller.on('open', function(client) {
console.log('Connect');
});
controller.on('message', function(client, message) {
console.log(message);
/*
var self = this;
var message = MODEL('message').schema;
var model = self.body;
var message = new message({ message: model.message }).save(function(err) {
if (err)
self.throw500(err);
// Read all messages
message.find(self.callback());
});
*/
});
controller.on('error', function(error, client) {
framework.error(error, 'websocket', controller.uri);
});
}
Any help Please!!!
This is complete project
---Update---
In this function i use to save data to MongoDB
but it didn't give any error.also Didnt save the data to database.i not sure my code is write or wrong
controller.on('message', function(client, message) {
console.log(message);
/*
var self = this;
var message = MODEL('message').schema;
var model = self.body;
var message = new message({ message: model.message }).save(function(err) {
if (err)
self.throw500(err);
// Read all messages
message.find(self.callback());
});
*/
});
This my mongoose.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://totaldemo:123456#ds029979.mongolab.com:29979/totaldemo');
global.mongoose = mongoose;
This is my user.js
var userSchema = mongoose.Schema({ user: String})
exports.schema = mongoose.model('user', userSchema,'user');
exports.name = 'user';
I don't know totaljs framework at all, but i see some issues already with plain javascript.
First of all, i suggest You set up Your model like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
user: String
});
module.exports = mongoose.model('User', userSchema);
and then in controller, when You import:
var User = require('path/to/user/file')
You can use it like this straight away:
User.find()
Also - i totally dont get what are You doing later.
You defined user model and exported NOTHING MORE than a STRING. Only tthing it will do is, that when You import that user to variable User, the User.name will === to 'user' string. so in Your example it would be:
var User = require('path/to/user/model/file')
console.log(User.name) // prints 'user'
and nothing more! There are no models attached to that export. Maybe its how totaljs works, but i VERY doubt it.
Later on - You try to ... use message model. Where it comes from? You defined user model, not message model.
Another thing - as i stated - i dont know totaljs, but I doubt it ask YOu to define var model, and then never use variable model.
I strongly suggest using plain node with mongoose first, then try to integrate it with any fullstack.
For sure its not a solution, but maybe it points out some problems in Your code and will help.
EDIT:
I looked quickly in totaljs, and it looks that You really should export string (which is little weird and doing magic stuff:) ), but its NOT mongoose, and i guess will ONLY work with native totaljs model solution. You cant use mongoose and totaljs like that. I dont know how much not using native totaljs models system ruins framework other options, but its probably safer to use native one.
Honestly, i dont have time to look deeper into docs, but google says nothing about sql or even mongo inside of totaljs docs... so, You have to figure it out :)
EDIT2 i found https://github.com/totaljs/examples/tree/master/mongoose and it looks weird... check if that example works (looks like You seen it, Your code is similar :)). check if You're mongod is working, check if You can conenct from plain node...
Honestly sorry, i surrender. Totaljs has to much magic and abstraction for me to help You out with this :(. Hope You will find Your answer.

Updating user list in client upon disconnection

Good day guys. Upon solving my problem here in SO. I successfully added user in my array users[] in socket.io and showed the connected users in the client side.
Upon the user disconnection the name of the user will be deleted using this code delete users[socket.user]; but the name of the user remains in the client.
Can you help me on removing the name of the user guys? Thanks.
Here's my server.js
var redis = require('redis');
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8080);
var users = [];
app.get('/', function (req, res) {
res.sendfile(__dirname + '/test.html');
});
io.sockets.on('connection', function (socket) {
socket.on('adduser', function (user) {
socket.user = user;
users.push(user);
updateClients();
});
socket.on('disconnect', function () {
delete users[socket.user];
updateClients();
});
function updateClients() {
io.sockets.emit('update', users);
}
});
And here's my client.html.
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
var userList = [];
socket.on('connect', function (){
socket.emit('adduser', prompt("What's your name?"));
});
socket.on('update', function (users){
userList = users;
$('#user').empty();
for(var i=0; i<userList.length; i++) {
$('#user').append("<b>" + userList[i] + "</b></br>");
}
});
</script>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
<b>Users</b>
<div id="users">
<p id="user"></p>
</div>
</div>
I don't know what to put in the socket.on('disconnect', function() {}); so the disconnected user and the name of the user will be removed in the client side.
The reason the clients are not updating correctly client-side is because you aren't removing the correctly server-side. You can't delete an array key by its content with delete. Instead, do this:
socket.on('disconnect', function() {
users.splice(users.indexOf(socket.user), 1);
updateClients();
});
The problem with what you're doing is you're effectively doing this:
var users = [];
users.push('foo');
delete users['foo'];
Since arr is an array, users['foo'] will map to undefined. The string foo is actually index one of the array, so you'd have to use delete users[0], which would cause the array key to be still exist but be undefined:
users[0] // undefined
Instead, you should remove the key entirely:
var index = users.indexOf(socket.user);
users.splice(index, 1);
You can't access an array item by content. Write a function to iterate across the users array to remove it.
function removeUser(username){
var users2 = [];
users.forEach(function(user){
if(user === username){ return;} // do nothing this iteration
users2.push(user); // if we haven't returned yet, add to users2
});
users = users2;
return users2;
};
socket.on('disconnect', function() {
removeUser(socket.user);
updateClients();
});

Categories