代码之家  ›  专栏  ›  技术社区  ›  Arkellys

Socket.io,从默认命名空间发送到自定义命名空间不工作

  •  0
  • Arkellys  · 技术社区  · 7 年前

    我有一个使用Socket.io的React应用程序。我使用默认名称空间 / 和自定义名称空间 /test . 我需要能够从一个名称空间发射到另一个名称空间,但我只设法让它从自定义工作到默认工作。

    在客户端,事件侦听器位于根目录上( App.js

    componentDidMount() {
      socket.on('test_listener', (data) => {
        // Some code
      })
    }
    

    使用redux初始化连接:

    import socketIOClient from 'socket.io-client';
    
    const initialState = {
      initializeSocket: socketIOClient('http://localhost:3000/'),
      ...
    }
    

    在服务器端,以下是代码:

    io.on('connection', function (socket) { 
    
      socket.on('something', (data) => {
    
        io.of('/test').emit('test_listener', data); // Not working
        socket.broadcast.emit('test_listener', data); // Is working
    
      })
    
    });
    

    io.of('namespace').emit('event_name', data); 它应该按照固定在房间里的方式工作 Socket.io's Emit cheatsheet . 客户端的事件侦听器正在工作,因为我从 broadcast.emit .

    另外,我可以从 /试验 到

    socket.on('join_namespace_test', data => {
    
      // [...] Some code to check if the namespace exists
    
      io.of('/test').on('connection', function (nspSocket) {
    
        nspSocket.on('do_something', (data) => {
          io.of('/').emit('another_action', data); // This one is working fine
        })
    
      })
    
      // [...] Some code to add the user to the namespace /test (switching from default)
    }
    

    你知道为什么会有这样的现象吗 到 它不起作用了吗?


    编辑: 经过进一步研究,我发现 this post :

    为了确保这个问题不是来自项目的另一部分,我在小提琴上复制了这个问题。“从默认值发射到自定义”仍然不起作用,我还注意到 broadcast 当客户端从默认值切换到自定义值,然后返回默认值时,会出现一种奇怪的行为(它会向发送方发送消息,但不应该发送)。

    2 回复  |  直到 7 年前
        1
  •  0
  •   Arkellys    7 年前

    socket.on 如果已初始化,则它将仅在设置了的命名空间/连接上工作。 This post helped me to find the solution .

    var socket = io();
    listen();
    
    function switchNamespace(namespace) {
      socket.close(); // Close the current connection
      socket = io(namespace);
      listen();
    }
    
    function listen() {
      socket.on('test_listener', (data) => {
        // Some code
      })
    }
    

    io.of('/namespace').on('connection', ... 在默认值的内部或外部 io.on('connection', ... 没什么区别。

        2
  •  0
  •   Tronix117    7 年前

    应该是这样的:

    const socket = io('/test')
    

    如果你在电视上广播什么 default / 名称空间而不是 /test 一

    const socketDefault = io()
    const socketTest = io('/test')
    

    class Sockets {
    
      // Used as Handler for the proxy for `multi` method, should work, but didn't test it
      get (target, prop) {
        return (...args) => {
          const output = [];
          for(const alias of target._aliases) {
            output.push(target._sockets[alias][prop](...args))
          }
          return output;
        }
      }
    
      // Used to proxy methods, and only methods
      multi(aliases) {
        return new Proxy({ _sockets: this, _aliases: aliases }, this); // Use the above `get` for all undefined methods
      }
    
      addNamespace(alias, namespace) {
        if (this[alias]) {
          return false
        }
    
        Object.defineProperty(this, alias, {
          enumerable: true,
          writable: false,
          configurable: false,
          value: io(namespace)
        })
      }
    }
    
    const sockets = new Sockets()
    sockets.addNamespace('default')
    sockets.addNamespace('test', '/test')
    sockets.addNamespace('toto', '/toto')
    
    sockets.test.on('test_listener', (data) => {
      // Some code
    })
    
    sockets.toto.on('test_listener', (data) => {
      // Some code
    })
    
    sockets.multi(['test', 'toto', 'default']).on('common_listener', (data) => {
    
    })