0

I've found a lot of good background on this issue already on stackoverflow and in the socketio docs but I'm not able to apply what I've learned to fix my code base.

I encounter the issue when I try to get a list of all the clients in a namespace and specific room. In socketio version 2 (the old way) you are able to get a list of all the sockets in the /chat namespace and 'general' room using the code:

io.of("/chat").in('general').clients((error, clients) => {
  console.log(clients); // => [Anw2LatarvGVVXEIAAAD]
});

However, as of version 3 the .clients() method is no longer used and has been renamed .allSockets() which returns a promise-based Set data type:

await ioServer.of('/chat').in('general').allSockets();

I'm trying to use the .allSockets() syntax to grab the value within the returned promise for my /wiki namespace and current room which I've assigned to the variable roomToJoin but I'm missing something fundamental about how the async-await syntax should be used. I keep getting the error:

(node:46560) UnhandledPromiseRejectionWarning: TypeError: ioServer.of(...).in(...).allSockets is not a function

My code and files are below. Any help would be greatly appreciated.

slack.js

const express = require("express");
const app = express();
const Server = require("socket.io");

let namespaces = require("./data/namespaces");
app.use(express.static(__dirname + "/public"));
const expressServer = app.listen(9000);
const ioServer = new Server(expressServer);

ioServer.on("connection", (socket) => {
  let nsData = namespaces.map((ns) => {
    return {
      img: ns.img,
      endpoint: ns.endpoint,
    };
  });
  socket.emit("nsList", nsData);
});

namespaces.forEach((namespace) => {
  ioServer.of(namespace.endpoint).on("connection", (nsSocket) => {
    nsSocket.emit("nsRoomLoad", namespaces[0].rooms);

    nsSocket.on("joinRoom", async (roomToJoin, numberOfUsersCallback) => {
      nsSocket.join(roomToJoin);
     
    const clients = await ioServer.of('/wiki').in(roomToJoin).allSockets();
    console.log(Array.from(clients));

      numberOfUsersCallback();
    });
  });
});

clientScripts.js

const socket = io("http://localhost:9000");
let nsSocket = "";

socket.on("nsList", (nsData) => {
  let namespacesDiv = document.querySelector(".namespaces");
  namespacesDiv.innerHTML = "";
  nsData.forEach((ns) => {
    namespacesDiv.innerHTML += `<div class="namespace" data-ns=${ns.endpoint} ><img src="${ns.img}" /></div>`;
  });

  Array.from(document.getElementsByClassName("namespace")).forEach((elem) => {
    elem.addEventListener("click", (e) => {
      const nsEndpoint = elem.getAttribute("data-ns");
      console.log(`${nsEndpoint} I should go to now`);
    });
  });
  joinNs('/wiki');
});

joinNs.js

function joinNs(endpoint) {
  nsSocket = io(`http://localhost:9000${endpoint}`);
  nsSocket.on("nsRoomLoad", (nsRooms) => {
    let roomList = document.querySelector(".room-list");
    roomList.innerHTML = "";
    nsRooms.forEach((room) => {
      let glyph;
      if (room.privateRoom) {
        glyph = "lock";
      } else {
        glyph = "globe";
      }
      roomList.innerHTML += `<li class='room'><span class="glyphicon glyphicon-${glyph}"></span>${room.roomTitle}</li>`;
    });
    let roomNodes = document.getElementsByClassName("room");
    Array.from(roomNodes).forEach((elem) => {
      elem.addEventListener("click", (e) => {
        console.log("Someoneclickon ", e.target.innerText);
      });
    });

    const topRoom = document.querySelector(".room");
    const topRoomName = topRoom.innerText;
    joinRoom(topRoomName);

  });

  nsSocket.on("messageToClients", (msg) => {
    console.log(msg);
    document.querySelector("#messages").innerHTML += `<li>${msg.text}</li>`;
  });

  document
    .querySelector(".message-form")
    .addEventListener("submit", (event) => {
      event.preventDefault();
      const newMessage = document.querySelector("#user-message").value;
      socket.emit("newMessageToServer", { text: newMessage });
    });
}

joinRoom.js

function joinRoom(roomName) {
  nsSocket.emit("joinRoom", roomName, (newNumberOfMembers) => {
    document.querySelector(
      ".curr-room-num-users"
    ).innerHTML = `${newNumberOfMembers} <span class="glyphicon glyphicon-user">`;
  });
}

namespaces.js

// Bring in the room class
const Namespace =  require('../classes/Namespace');
const Room =  require('../classes/Room');

// Sets up the namespaces. 
// Todo: create/populate namespaces and rooms from data stored in the DB.
//  SYNTAX for new Namespace(id, nsTitle, img, endpoint)
let namespaces = [];
let wikiNs = new Namespace(0,'Wiki','https://upload.wikimedia.org/wikipedia/en/thumb/8/80/Wikipedia-logo-v2.svg/103px-Wikipedia-logo-v2.svg.png','/wiki');
let mozNs = new Namespace(1,'Mozilla','https://www.mozilla.org/media/img/logos/firefox/logo-quantum.9c5e96634f92.png','/mozilla');
let linuxNs = new Namespace(2,'Linux','https://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png','/linux');

namespaces.push(wikiNs,mozNs,linuxNs);

// Make the main room and add it to rooms. it will ALWAYS be 0
//   SYNTAX for new Room(roomId, roomTitle, namespace)
wikiNs.addRoom(new Room(0,'General','Wiki', true));
wikiNs.addRoom(new Room(1,'New Articles','Wiki', true));
wikiNs.addRoom(new Room(2,'Editors','Wiki'));
wikiNs.addRoom(new Room(3,'Other','Wiki'));

mozNs.addRoom(new Room(0,'General','Mozilla'));
mozNs.addRoom(new Room(1,'Firefox','Mozilla'));
mozNs.addRoom(new Room(2,'SeaMonkey','Mozilla'));
mozNs.addRoom(new Room(3,'SpiderMonkey','Mozilla'));
mozNs.addRoom(new Room(4,'Rust','Mozilla'));

linuxNs.addRoom(new Room(0,'General','Linux'));
linuxNs.addRoom(new Room(1,'Debian','Linux'));
linuxNs.addRoom(new Room(2,'Red Hat','Linux'));
linuxNs.addRoom(new Room(3,'MacOs','Linux'));
linuxNs.addRoom(new Room(4,'Kernal Development','Linux'));


module.exports = namespaces;

Namespace.js

class Namespace{
    constructor(id, nsTitle, img, endpoint){
        this.id=id;
        this.img=img;
        this.nsTitle=nsTitle;
        this.endpoint=endpoint;
        this.rooms = [];
    }

    addRoom(roomObj){
        this.rooms.push(roomObj);
    }
}

  module.exports = Namespace;

Room.js

class Room{
    constructor(roomId, roomTitle, namespace, privateRoom = false){
        this.roomId=roomId;
        this.roomTitle = roomTitle;
        this.namespace = namespace;
        this.privateRoom = privateRoom;
        this.history = [];
    }
    addMessage(message){
        this.history.push(message);
    }
    clearHistory(){
        this.history = [];
    }
}

module.exports = Room;

chat.html

<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
  integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
  crossorigin="anonymous"
/>
<link rel="stylesheet" type="text/css" href="./styles.css" />

<div class="container-fluid">
  <div class="row">
    <div class="col-sm-1 namespaces">
      <!-- JS WILL UPDATE THIS DYNAMICALLY -->
    </div>
    <div class="col-sm-2 rooms">
      <h3>Rooms</h3>
      <ul class="room-list">
        <!-- JS WILL UPDATE THIS DYNANIMICALLY -->
      </ul>
    </div>
    <div class="chat-panel col-sm-9">
      <div class="room-header row col-6">
        <div class="col-sm-3">
          <span class="curr-room-text">Current Room</span>
          <span class="curr-room-num-users"
            >Users <span class="glyphicon glyphicon-user"></span
          ></span>
        </div>
        <div class="col-sm-3 search pull-right">
          <span class="glyphicon glyphicon-search"></span>
          <input type="text" id="search-box" placeholder="Search" />
        </div>
      </div>
      <div class="message-form">
        <form id="user-input">
          <div class="col-sm-12">
            <input
              id="user-message"
              type="text"
              placeholder="Enter your message"
            />
          </div>
          <!-- <div class="col-sm-2">
                        <input class="btn btn-primary" type="submit" value="send" />
                    </div> -->
        </form>
      </div>
      <ul id="messages" class="col-sm-12">
        <li>
          <div class="user-image">
            <img src="https://via.placeholder.com/30" />
          </div>
          <div class="user-message">
            <div class="user-name-time">rbunch <span>1:25 pm</span></div>
            <div class="message-text">I went running today.</div>
          </div>
        </li>

        <li>
          <div class="user-image">
            <img src="https://via.placeholder.com/30" />
          </div>
          <div class="user-message">
            <div class="user-name-time">rbunch <span>2:25 pm</span></div>
            <div class="message-text">
              I'm getting my tires changed this afternoon.
            </div>
          </div>
        </li>
        <li>
          <div class="user-image">
            <img src="https://via.placeholder.com/30" />
          </div>
          <div class="user-message">
            <div class="user-name-time">rbunch <span>2:29 pm</span></div>
            <div class="message-text">I like history.</div>
          </div>
        </li>
        <li>
          <div class="user-image">
            <img src="https://via.placeholder.com/30" />
          </div>
          <div class="user-message">
            <div class="user-name-time">rbunch <span>2:59 pm</span></div>
            <div class="message-text">What day is tomorrow?.</div>
          </div>
        </li>
      </ul>
    </div>
  </div>
</div>

<script src="/socket.io/socket.io.js"></script>
<script src="/clientScripts.js"></script>
<script src="/joinNs.js"></script>
<script src="/joinRoom.js"></script>

ahauser
  • 3
  • 1

0 Answers0