Node.js: Removing users in Socket.IO - javascript

i'm having problems in removing users in Socket.IO, upon their browser close the user in the array users[] is not removed and not updated and i would like also to update the users in the client side. Can you help me remove user programmatically? Here is my code guys, i hope you can help me with my code provided below. I've already surfed the net on how to remove users but i can't really make it work. Thanks in advance guys.
Here is 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);
var publish = redis.createClient();
var subscribe = redis.createClient();
server.listen(8080);
var users = [];
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.on('adduser', function (user) {
users[user] = user;
console.log(users);
});
socket.on('disconnect', function (user) {
delete users[user] = user;
io.sockets.emit('update', user);
// delete users[user] = users;
// socket.emit('update', users);
console.log(users)
});
socket.on('update', function () {
users[user] = user;
console.log('Current users: ', users);
});
});
Here is my client.html:
<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');
socket.on('connect', function(){
socket.emit('adduser', prompt("What's your name?"));
});
</script>
<div style="float:left;width:150px;border-right:2px solid black;height:510px;padding:10px;overflow:scroll-y;text-align:center;">
<b>Users</b>
<div id="users"></div>
</div>
</html>
Thanks again guys, i hope you can help me :)

The server-side disconnect event isn't going to have a user variable in its callback, so you are effectively using delete users[null]. Instead, you should be storing the user variable in the socket-specific data store, like so:
var io = require('socket.io').listen();
var users = [];
io.sockets.on('connection', function(socket) {
socket.on('adduser', function(user) {
socket.set('username', user, function() {
users[user] = user;
});
});
socket.on('disconnect', function() {
socket.get('username', function(err, user) {
delete users[user];
io.sockets.emit('update', users);
});
});
});
When the socket disconnects, you can then find its associated user variable, and then delete it.

Related

Node.js socket.io returning multiple values for a single event

I'm trying to build a simple app using Node, Express (^4.15.3), and socket.io (^2.0.3). I'm building a simple chat app, however each time I add a new message, I get an additional response each time.
For example, if the first message was "Hello", I would be returned:
Hello
If I then add a subsequent message of "Is anyone there?", I get back:
Is anyone there?
Is anyone there?
And so on...each time I get an additional response back.
Here's my code - it feels like it's something really obvious and I may have been staring at it too long...
//app.js
var express = require("express");
var bodyParser = require("body-parser");
var expressValidator = require('express-validator');
var session = require('express-session');
var passport = require("passport");
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
app.use(express.static("public"));
app.set("view engine", "ejs");
server.listen(process.env.PORT || 3000, process.env.IP, function(){
console.log("Server starting...");
});
app.get('/testsocket', function(req, res){
res.render('sockets/test');
});
io.sockets.on('connection', function(socket){
console.log('Connected')
socket.on('send message', function(data){
console.log('Got the message...');
io.sockets.emit('new message', data)
});
});
And then client side
//client side
$(function() {
var socket = io.connect();
var $messageForm = $('#send-message');
var $messageBox = $('#message');
var $chat = $('#chat');
$messageForm.submit(function(e){
e.preventDefault();
socket.emit('send message', $messageBox.val());
$messageBox.val('');
socket.on('new message', function(data){
$chat.append(data + "<br>");
});
});
});
I think the problem is that you're registering the listener for new message inside your submit function. So each time you submit the form you register a new listener, in addition to any previous listeners. Try putting the socket.on('new message', ... section outside the submit handler.

socket.io is not refreshing data

I am trying to display filesize on with socket.io with every time file changes. Here is my js code.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendfile('index.html');
});
var fs = require("fs");
var filesize;
var filename = 'D:\\test.txt';
fs.watchFile(filename, function() {
fs.open(filename, 'r', function(err, fd) {
fs.stat(filename, function(err, stat) {
if(err) { console.log('error'); }
console.log(stat.size);
filesize = stat.size;
});
})
});
io.on('connection', function(socket){
console.log('A user connected');
socket.emit('testerEvent', { description: prntarr});
socket.on('clientEvent', function(data){
console.log(data);
});
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
The problem is , socket is not refreshing data but console shows changed size. It refreshes only when i reload the page. Please suggest where i am making mistake and how to fix it.
thanks in advance.
You need to do a socket.emit() inside your fs.watchFile() callback. You're not emitting anything when the file changes at the moment
When a user connects, push his socket in an Array.
Inside the watchFile callback, iterate through the connected sockets Array and .emit() what you want to send.
Don't forget to remove from that
Array any sockets that have disconnected

socket.io not recieving/sending

I have a simple setup where I have some draggable divs and I want to use sockets.io to update the position between clients.
On my client (index.html) I have :
// find the elements
var elements = document.getElementsByClassName('ball'),
labelsX = document.getElementsByClassName('coords-x'),
labelsY = document.getElementsByClassName('coords-y');
// loop over the 3 items...
for (var n = elements.length; n--;) {
// ... augment our default options with individual `onDrag` handlers
var opts = {
onDrag: onDragFactory(n),
setCursor: true
};
// ... and initialize drag for each
window.d = new Draggable(elements[n], opts);
console.log('ddd');
}
// bind `n` to its value at iteration time
function onDragFactory (n) {
return function (element, x, y) {
//This doesnt seem to work
console.log(elements[n].style.top);
socket.emit('positionx', elements[n].style.top);
socket.on('positionx', function(positionx){
elements[n].style.top= positionx.value();
});
}
}
My server is then :
var express = require('express');
var path = require('path');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var publicPath = path.resolve(__dirname, 'public');
app.use(express.static(publicPath));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
//Server Side Listen for an event from the client
io.on('connection', function(socket){
socket.on('positionx', function(positionx){
console.log('recieving');
console.log(positionx);
io.emit('positionx', positionx);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
The server however doesn't seem to receive any information. Is there something I'm doing wrong? Any help would be much appreciated!
In your client you need to define socket.
var socket = io();
Also, make sure you are including socket.io-x.x.x.js prior to calling socket.io in your javaScript. You are probably already doing this, but it's unclear without seeing more code.

How to listen with node.js and redis Laravel 5 events

In Laravel 5 not implemented ShouldBroadCast method, any idea how I can implement it manualy?
Here is my try.
This is handler for ProjectNotificationEvent:
<?php namespace App\Handlers\Events;
use App\Events\ProjectNotificationEvent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;
use App\Notification;
use Illuminate\Support\Facades\Redis;
class NotifyUserAboutGroup {
CONST CHANNEL = 'update.group';
public function handle(ProjectNotificationEvent $event)
{
foreach ($event as $events){
$redis = Redis::connection();
$redis->publish(self::CHANNEL, $events->name);
}
}
}
This is node.js:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('update.group', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log('Message Recieved: ' + message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
And on client side in my view I have this:
var socket = io.connect('127.0.0.1:3000');
socket.on("update.group:App\\Events\\ProjectNotificationEvent", function(message){
// increase the power everytime we load test route
console.log(message);
});
Problem is on client side console.log don't return anything.
Any solution for this?
var socket = io.connect('127.0.0.1:3000');
socket.on('message', function (data) {
console.log(data);
});
Please try this

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