1
votes

La diffusion Socket IO vers la pièce ne fonctionne pas correctement

S'il s'agit d'une question vague, merci de me le faire savoir, afin que je puisse préciser. Je veux vraiment contourner ce problème.

J'ai lu plusieurs feuilles de triche sur la façon de diffuser correctement un message dans une salle client. Ma référence est: https://github.com/socketio/ socket.io/blob/master/docs/emit.md .

Pour décrire mon problème: La page de chat affiche correctement le bouton d'envoi, mais dès que je clique sur envoyer, rien n'est jamais envoyé.

Ce qui est intéressant, c'est que chaque fois que je n'utilise pas de salles, et que je n'utilise que l'espace de noms par défaut, je peux recevoir des messages.

Une idée de ce qui se passe? Merci !!

server.js

router.post('/available', ensureAuthenticated, (req,res,next) => {
    var io = res.locals['socketio']
    db.collection('DefaultUser').update({_id: req.user._id}, {$set: {isAvailable: true}});
    res.redirect('../chat')
})

chat.jade

extends layout


block content

    h2.page-header(style = "text-align: center;").
        Home Page

    if (user.isTutor)
        b(style = "text-align: center;")
            form(method='post', action = '/home/available')
                input.btn.btn-primary(type = 'submit',name='isAvailable', value = 'Available', id = 'button4')
            form(method='post', action = '/home/unavailable')
                input.btn.btn-primary(type = 'submit',name='isUnavailable', value = 'Unavailable', id = 'button5')  
    script(src="/socket.io/socket.io.js")
    script.
        var btn = document.getElementById('button4')
        //var space = '#{user.room}'
        var socket = io.connect()
        btn.addEventListener('click', function() {
            socket.emit('subscribe', 'room1')
        })

    div(id = 'magic')
        form(method='get')
            if (user.hasApplied)
                input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/findatutor';" name='find', value = 'Find a Tutor', class = 'middle', id = 'button7')

            else if (user.hasApplied == false)
                input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/findatutor';" name='find', value = 'Find a Tutor', id = 'button1')
                input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/apply';"  name='become', value = 'Become a Tutor', id = 'button2')

extends layout

block content

 h2.page-header Chat Page
 div(id='the-chat')
  div(id='chat-window')
   div(id='output')
  input(id='handle', type='text', value = user.name, style= 'width: 0px; visibility: hidden;')
  input(id='message', type='text', placeholder='message')
  button(id='send' value='Send') Send

  //imports the socket.io functionality on the client side for the chat.jade application
  script(src="/socket.io/socket.io.js")

  script.

    //variable created that mirrors connection made in the backend

    //matches the connection made in the server side
    var socket = io.connect('http://localhost:3000')

    //Query dom
    var message = document.getElementById('message')
    var handle = document.getElementById('handle')
    var btn = document.getElementById('send')
    var output = document.getElementById('output')

    //emit events
    btn.addEventListener('click', function() {
      socket.emit('chat', {
        message: message.value,
        handle: handle.value
      })
    })


    socket.on('chat', function(data) {
      output.innerHTML += '<p><strong>' + data.handle + ': </strong>' + data.message + '</p>';
      document.getElementById('message').value = "";
    })

io.on('connection', function(socket) {
    global.rooms = 'room1';
    socket.on('subscribe', function(room) {
        socket.join(rooms);
        console.log(socket.id + 'joining room', rooms)
    })
    socket.on('chat', function(data) {
        io.to(rooms).emit('chat', data);
  })
})


4 commentaires

Y a-t-il quelqu'un dans cette pièce pour recevoir le message? Je ne vois nulle part dans chat.jade où vous émettez l'événement 'subscribe' sur le serveur afin que vous rejoignez la salle. Cet événement d'émission se situe-t-il dans une zone différente de l'application?


L'émetteur d'événement a été inclus ci-dessus dans le bouton home.jade. 2 choses devraient se produire lorsque l'utilisateur clique sur le bouton 'disponible' qui a un id = button4. Numéro un: ils doivent être redirigés vers le chat.jade et le numéro deux: ils doivent émettre un événement d'abonnement pour room1. Si cela est utile, je console.log (données) côté serveur et j'obtiens les données correctes chaque fois que je clique sur Soumettre. Le problème est que les informations ne sont pas diffusées côté client. Voici les résultats cmd: {message: 'hi', handle: 'William Sheppard'} @JamesPooley


J'ai également fourni un extrait de mon fichier home.js qui contient une demande de publication pour l'itinéraire `` disponible '' qui représente le bouton qui (1) redirigera vers la page de discussion et (2) initiera la connexion à room1 @JamesPooley


Vérifiez-moi à ce sujet. Lorsque vous naviguez de home.jade à chat.jade, ne vous déconnectez-vous pas et ne vous reconnectez-vous pas au socket? D'après ce que je sais, cela créerait une nouvelle instance d'objet de socket sur le serveur, ce qui signifie que le nouveau socket ne serait PAS abonné / dans la salle car il s'agit d'une nouvelle instance de socket. Essayez de tester en émettant l'événement d'abonnement au serveur dans le script chat.jade pour voir si cela fonctionne de cette façon. chat.jade var socket = io.connect ('http: // localhost: 3000') socket.on ('connect', function () {socket.emit ('subscribe', 'room1')}) < / code> puis essayez le chat


3 Réponses :


0
votes

Essayez

io.in(rooms).emit('chat', data);


2 commentaires

J'ai essayé cela, sans succès. J'ai inclus un "console.log (data)" juste après la ligne que vous venez de recommander ci-dessus et j'obtiens: {message: 'this is example text', handle: 'Bob Peterson'} @kevin


Donc, essentiellement, le message est capturé correctement, mais il n'est pas diffusé dans la salle.



0
votes

Manquant ceci sous global.rooms = 'room1';

var rooms = global.rooms

Réponse plus longue: Au moins ce que je peux voir, vous avez ajouté "rooms" comme une propriété sur l'objet global (idk où «global» lui-même est défini, mais s'il ne génère pas d'erreur, je suppose que vous l'avez défini ci-dessus). Bien qu'il s'agisse d'une propriété, la variable 'rooms' que vous utilisez comme espace de noms n'est pas définie au moment où vous l'appelez, elle ne sait donc pas où émettre le message.

Encore plus de réponse: De plus, si vous avez l'intention d'ajouter des salles supplémentaires à global.rooms, je pense que vous voudrez peut-être utiliser une liste de hachage pour les stocker, afin de pouvoir y accéder facilement en tant que global.rooms [room] , ainsi que d'ajouter facilement de nouvelles salles à la liste, c'est-à-dire global.rooms [room.name] = room


2 commentaires

Hm vous penseriez que son serveur lèverait également une erreur indéfinie? Je me demande si les chambres sont définies à nouveau quelque part au-dessus.


Pas nécessairement. Essayez ceci dans votre console: x = ""; x.charAt (non défini); Il l'utilise comme valeur, n'accédant à aucune propriété / fonction.



1
votes

Le problème est que vous n'avez pas spécifié où rendre les messages. Comme je l'ai compris, vous n'avez aucun problème à créer des salles, je vais donc vous expliquer étape par étape comment gérer après ce point.

Selon votre code, il s'agit de la communication entre le serveur et le client pour l'envoi de messages

const $messages = document.getElementById("messages");
const messageTemplate = document.getElementById("message-template").innerHTML;

Le premier client envoie le message (en tapant la zone de saisie) au serveur et lorsque le serveur le reçoit, il doit envoyer le même message à tous les autres clients. une fois que les clients reçoivent ce message, les clients doivent trouver comment l'afficher. Mais lorsque le serveur envoie le message reçu, vous devez alors lancer un nouvel événement. appelons cela affichage. votre code doit donc ressembler à ceci:

//this is where you are gonna display the message
<div id="messages" class="chat__messages"></div>

<!-- template messages -->
    <script id="message-template" type="text/html">
      <div>
          <p>{{message}}</p>
      </div>
    </script>

Maintenant, votre client doit être à l'écoute de cet événement et doit gérer où l'afficher:

// chat.jade

socket.on('display', (data) => {
    const displayedMessage = pug.render(messageTemplate, {
        message: data.message,
    })
    $messages.insertAdjacentHTML('beforeend', displayedMessage)
})

Depuis que Jade a été renommé pug, j'ai utilisé pug ici. Je vais donc rendre {message: data.message} en html dans une balise de script, puis je l'ai placé dans DOM ELEMENT $ message.

Je ne sais pas où vous voulez rendre handle: handle.value Je vais juste montrer comment afficher le message. de même, vous pouvez le gérer.

Maintenant que sont messageTemplate , $ messages et insertAdjacentHTML ()?

créer un div et une balise script dans votre html

//server.js
//i always use arrow functions, but I will follow along your code
     socket.on('chat', function(data) { 
            io.to(rooms).emit('display', data);
      })

//chat.jade

//server.js
 socket.on('chat', function(data) {
        io.to(rooms).emit('chat', data);
  })
//chat.jade
btn.addEventListener('click', function() {
      socket.emit('chat', {
        message: message.value,
        handle: handle.value
      })
    })

La méthode insertAdjacentHTML () insère un texte au format HTML, dans une position spécifiée. vous pouvez obtenir plus d'explications et d'exemples ici:

https: // www. w3schools.com/jsref/met_node_insertadjacenthtml.asp

Le code socket io semble long et compliqué, mais si vous connaissez la logique et que vous vous déplacez étape par étape, il sera facile de l'implémenter.


0 commentaires