javascriptnode.jsexpresssocket.ioserverside-javascript

Is there some way of importing a variable(specifically map) from the server side onto the client side(Socket.io)?


I am trying to assign unique colors to each different client( by using socket.id ). In my map() I have paired (socket.id,randomcolor()), but this variable is on the server side. I've found out that the require() statement doesn't work on client side,

  1. why is that and what is a solution to it? I want to be able to pass map() variable to the client side so that it uses the color assigned to that socket.id and displays the color accordingly.

  2. Or is there some way to know the socket.id on the client side(I don't think it is but not sure), specifically a users computer has to know who sent the message i.e. what socket.id was used to send the message, Is it possible to know that?

Here's my server side:

var express = require('express');
var app = express();
app.use(express.static('public'))
var http = require('http').createServer(app);
var io = require('socket.io')(http);


const map = new Map();



io.on('connection', function(socket) {
  console.log('connected by ' + socket.id);
  map.set(socket.id, RandomColor())
  socket.on('chat', function(data) {
    //emitting to all sockets connected
    io.emit('chat', data);
    console.log(map.entries());
  });

  socket.on('typing', function(data) {
    socket.broadcast.emit('typing', data);
  })
});



http.listen(3000, function() {
  console.log('listening on port 3000');
});

Here's client side :

// import '../index';
var socket = io.connect('http://localhost:3000')

var message = document.getElementById('Message');
var handle = document.getElementById('Handle');
var btn = document.getElementById('Send');
var output = document.getElementById('Output');
var feedback = document.getElementById('Feedback');

var ids = []
console.log(server);
//emit event
btn.addEventListener('click', function() {
  socket.emit('chat', {
    message: message.value,
    handle: handle.value,
  })
})

message.addEventListener('keypress', function() {
  socket.emit('typing', handle.value)
})
messageArray = []
//listening for any message received
socket.on('chat', function(data) {
  // console.log(data);  
  feedback.innerHTML = ""
  var item = document.createElement('li')
  item.innerHTML = "<span style=\"font-family:\"cursive\";\" ;><strong>" + data.handle + ": " + data.message + "</strong></span>";
  document.getElementById('Output').appendChild(item)
})

//listening for any typing event listener
socket.on('typing', function(data) {
  feedback.innerHTML = "<p><strong>" + data + " is typing a message </strong></p>";
})

PS: Also, I'm new to JS and Socket.io so please suggest some good practices for anything in the code.


Solution

  • First of all, JS has no built-in include/reference property.

    So you can't just join another file into another file. But some libraries achieve this with their own written methods etc.

    A JS executed on the client-side is not able to access local files. Although you may access an online file load into the document or to an object. So similar functionality can be achieved via 3rd party scripts.

    Node.JS follows the CommonJS module system and uses the power of being able to access the local file system.

    About the index: So you don't need a Map and Map is pretty similar to a standard object, main difference is might be the order of contents. But since all you need is a dictionary object. Just create a simple object. Then you can emit the color index whenever you want.

    const colorIndex = {}
    colorIndex[socketID] = color
    

    Each can set their color on client-side and send it to the server, on each update server has to update every other client about the color.

    A client cannot know other clients otherwise wouldn't be secure and it doesn't work like that. It works more like you are calling someone and the server is a middle man that connecting you two.

    So, create an object, store socket ids, nicknames, any other info you need. Keep it on serverside, on each message send all of them together with the message.

    const users = {}
    
    io.on('connection', function(socket) {
      users[socket.id] = {//Add new user
       color:RandomColor()
      }
    
      socket.on('chat', function(message) {
        let u = users[socket.id];//Get user from index
        let data = {//Create a message package
         user:(u.username)?u.username:"Guest", //name of the user if set
         color:u.color,//color of user
         message
        }
        io.emit('chat', data );//Send
      });
    
      socket.on('setColor', function(color) {//User can update color
        users[socket.id].color = color
      });
    
      socket.on('setname', function(name) {//User can update username
        users[socket.id].username = name
      });
    });
    

    So you probably get the idea. There are bunch of ways to achieve.