2016-08-16 55 views
0

我一直在擺弄socket.io幾天,遇到了這個問題。在我更新server.js中的currentRoom變量後,套接字仍然指向第一個房間集,在這種情況下,默認房間是「常規」。爲什麼我不能將當前房間保存在Socket.IO中?

當套接字離開其舊房間加入新房間時,發送的消息不會按照預期發送到新房間,而是發送到舊房間,即使當前房間存儲在變量中並且被用作定位插座的房間的手段。

我server.js:

const express = require('express'); 
const http = require('http'); 
const bodyParser = require('body-parser'); 
const socketIo = require('socket.io'); 
const webpack = require('webpack'); 
const webpackDevMiddleware = require('webpack-dev-middleware'); 
const webpackConfig = require('./webpack.config'); 

const app = express(); 
const server = http.createServer(app); 
const io = socketIo(server); 

app.use(express.static(__dirname + '/public')); 
app.use(webpackDevMiddleware(webpack(webpackConfig))); 
app.use(bodyParser.urlencoded({ extended: false })); 

io.on('connection', socket => { 
    var rooms = ['General']; 
    var currentRoom; 
    const defaultRoom = 'General'; 

    socket.join('General'); 
    currentRoom = "General"; 

    //socket.emit('setup', { rooms:rooms, currentRoom: currentRoom }); 

    socket.on('new room', room => { 
    socket.leave(currentRoom) 
    currentRoom = room; 
    socket.join(currentRoom); 
    socket.emit('new room', room); 
    console.log("New room has been created called: " + currentRoom); 
    }) 

    socket.on('message', body => { 
    console.log("Sending message to current room: " + currentRoom); 
    socket.to(currentRoom).emit('message', { 
     body, 
     from: socket.id.slice(8) 
    }) 
    }) 
}) 

server.listen(3000); 

在前端我有這樣的反應成分info.js

import React from 'react'; 
import io from 'socket.io-client'; 

import Room from './Room'; 
import RoomList from './RoomList'; 
import User from './User'; 
import UserList from './UserList'; 

export default class Info extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     users: [], 
     rooms: [], 
     currentRoom: '' 
    } 
    } 

    componentDidMount(){ 
    this.socket = io('/'); 
    //set defaults for room list 
    this.socket.on('setup', data => { 
     this.setState({ rooms: [...this.state.rooms, data.rooms] }); 
     this.setState({ currentRoom: data.currentRoom }); 
    }) 
    this.socket.on('new room', room => { 
     this.setState({ currentRoom: room }); 
    }) 
    } 

    userSubmit = event => { 
    const username = event.target.value 
    if(event.keyCode === 13 && username){ 
     this.setState({ users: [...this.state.users, username] }); 
     this.socket.emit('new user', username) 
     event.target.value = ''; 
    } 
    } 

    roomSubmit = event => { 
    const room = event.target.value 
    if(event.keyCode === 13 && room){ 
     this.setState({ rooms: [...this.state.rooms, room] }); 
     this.socket.emit('new room', room) 
     event.target.value = ''; 
    } 
    } 

    render(){ 
    const rooms = this.state.rooms.map((room, index) => { 
     return <li key={index}>{room}</li> 
    }) 

    const users = this.state.users.map((user, index) => { 
     return <li key={index}>{user}</li> 
    }) 
    return(
     <div class="chat-info"> 
     <RoomList rooms={rooms}/> 
     <Room roomSubmit={this.roomSubmit}/> 

     <UserList users={users}/> 
     <User userSubmit={this.userSubmit}/> 
     <p>Current Room: {this.state.currentRoom}</p> 
     </div> 
    ) 
    } 
} 

當我改變通過 '新房間' 活動室,當前房間確實得到更新,並且插座似乎加入新房間;然而,當套接字使用「消息」事件向當前房間發送消息時,套接字的消息被髮送到默認房間「常規」。爲什麼會發生?我是Socket.IO的新手,所以有可能是我看不到的東西。任何幫助,將不勝感激。乾杯!

編輯:從執行console.log在從新的房間和消息事件服務器JS,我得到了我的終端:

New room has been created called: new //new refers to the value of currentRoom 
Sending message to current room: General //General refers to the value of currentRoom 

這些終端的消息來,我已經創建了客戶端上的新房間後試圖在創建並加入新房間後發送消息。正如你所看到的,我已經創建並加入了一個簡稱爲「新」的新房間,但是當我嘗試向當前房間發送消息時,消息被髮送到「常規」房間。

編輯#2:這是我在我的server.js文件上運行的調試日誌。

 express:router dispatching GET /bundle.js +56ms 
     express:router query : /bundle.js +0ms 
     express:router expressInit : /bundle.js +1ms 
     express:router serveStatic : /bundle.js +0ms 
     send stat "/Users/alexwerner/Desktop/development/Web Development/rooms.io/public/bundle.js" +0ms 
     express:router webpackDevMiddleware : /bundle.js +1ms 
     engine intercepting request for path "/socket.io/" +149ms 
     engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogAC" +0ms 
     engine handshaking client "wlJpbWQIxMnTHrEYAAAA" +2ms 
     engine:socket sending packet "open" ({"sid":"wlJpbWQIxMnTHrEYAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}) 
+1ms 
     engine:polling setting request +1ms 
     engine:socket flushing buffer to transport +0ms 
     engine:polling writing "  �0{"sid":"wlJpbWQIxMnTHrEYAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}" 
+3ms 
     engine:socket executing batch send callback +1ms 
     socket.io:server incoming connection with id wlJpbWQIxMnTHrEYAAAA +0ms 
     socket.io:client connecting to namespace/+1ms 
     socket.io:namespace adding socket to nsp/+0ms 
     socket.io:socket socket connected - writing packet +1ms 
     socket.io:socket joining room /#wlJpbWQIxMnTHrEYAAAA +0ms 
     socket.io:client writing packet {"type":0,"nsp":"/"} +0ms 
     socket.io-parser encoding packet {"type":0,"nsp":"/"} +1ms 
     socket.io-parser encoded {"type":0,"nsp":"/"} as 0 +0ms 
     engine:socket sending packet "message" (0) +0ms 
     socket.io:socket joining room General +1ms 
     socket.io:socket joined room /#wlJpbWQIxMnTHrEYAAAA +0ms 
     socket.io:socket joined room General +0ms 
     engine intercepting request for path "/socket.io/" +1ms 
     engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogAJ" +0ms 
     engine handshaking client "Mh_obCHm_rGKbN2NAAAB" +1ms 
     engine:socket sending packet "open" ({"sid":"Mh_obCHm_rGKbN2NAAAB","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}) 
+0ms 
     engine:polling setting request +0ms 
     engine:socket flushing buffer to transport +0ms 
     engine:polling writing "  �0{"sid":"Mh_obCHm_rGKbN2NAAAB","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":60000}" 
+1ms 
     engine:socket executing batch send callback +0ms 
     socket.io:server incoming connection with id Mh_obCHm_rGKbN2NAAAB +0ms 
     socket.io:client connecting to namespace/+1ms 
     socket.io:namespace adding socket to nsp/+0ms 
     socket.io:socket socket connected - writing packet +0ms 
     socket.io:socket joining room /#Mh_obCHm_rGKbN2NAAAB +0ms 
     socket.io:client writing packet {"type":0,"nsp":"/"} +0ms 
     socket.io-parser encoding packet {"type":0,"nsp":"/"} +0ms 
     socket.io-parser encoded {"type":0,"nsp":"/"} as 0 +0ms 
     engine:socket sending packet "message" (0) +1ms 
     socket.io:socket joining room General +0ms 
     socket.io:socket joined room /#Mh_obCHm_rGKbN2NAAAB +0ms 
     socket.io:socket joined room General +0ms 
     engine upgrading existing transport +40ms 
     engine:socket might upgrade socket transport from "polling" to "websocket" +1ms 
     engine intercepting request for path "/socket.io/" +4ms 
     engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogB2&sid=wlJpbWQIxMnTHrEYAAAA" 
+0ms 
     engine setting new request for existing client +0ms 
     engine:polling setting request +0ms 
     engine:socket flushing buffer to transport +0ms 
     engine:polling writing "�40" +1ms 
     engine:socket executing batch send callback +0ms 
     engine intercepting request for path "/socket.io/" +0ms 
     engine handling "GET" http request "/socket.io/?EIO=3&transport=polling&t=LQMogB4&sid=Mh_obCHm_rGKbN2NAAAB" 
+0ms 
     engine setting new request for existing client +0ms 
     engine:polling setting request +0ms 
     engine:socket flushing buffer to transport +0ms 

請注意,有兩個套接字被創建;但是,我一次只能在一個瀏覽器上打開應用程序。我不知道這是如何socket.io如何工作,或者這可能是我的問題。

事件日誌:

socket.io-parser decoded 2["new room","New Room"] as {"type":2,"nsp":"/","data":["new room","New Room"]} +0ms 
    socket.io:socket got packet {"type":2,"nsp":"/","data":["new room","New Room"]} +0ms 
    socket.io:socket emitting event ["new room","New Room"] +0ms 
    socket.io:socket leave room General +0ms 
    socket.io:socket joining room New Room +0ms 
    socket.io:client writing packet {"type":2,"data":["new room","New Room"],"nsp":"/"} +0ms 
    socket.io-parser encoding packet {"type":2,"data":["new room","New Room"],"nsp":"/"} +0ms 
    socket.io-parser encoded {"type":2,"data":["new room","New Room"],"nsp":"/"} as 2["new room","New Room"] +0ms 
    engine:socket sending packet "message" (2["new room","New Room"]) +0ms 
    engine:socket flushing buffer to transport +0ms 
    engine:ws writing "42["new room","New Room"]" +1ms 
New room has been created called: New Room 
    socket.io:socket left room General +0ms 
    socket.io:socket joined room New Room +0ms 
    engine:ws received "42["message","Test Post"]" +11s 
    engine:socket packet +1ms 
    socket.io-parser decoded 2["message","Test Post"] as {"type":2,"nsp":"/","data":["message","Test Post"]} +0ms 
    socket.io:socket got packet {"type":2,"nsp":"/","data":["message","Test Post"]} +0ms 
    socket.io:socket emitting event ["message","Test Post"] +0ms 
Sending message to current room: General 
    socket.io-parser encoding packet {"type":2,"data":["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}],"nsp":"/"} +14.8m 
    socket.io-parser encoded {"type":2,"data":["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}],"nsp":"/"} as 2["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}] +0ms 
    socket.io:client writing packet ["2[\"message\",{\"body\":\"Test Post\",\"from\":\"aDw0sZU_XZAAAE\"}]"] +0ms 
    engine:socket sending packet "message" (2["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]) +0ms 
    engine:socket flushing buffer to transport +0ms 
    engine:ws writing "42["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]" +0ms 
    socket.io:client writing packet ["2[\"message\",{\"body\":\"Test Post\",\"from\":\"aDw0sZU_XZAAAE\"}]"] +1ms 
    engine:socket sending packet "message" (2["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]) +0ms 
    engine:socket flushing buffer to transport +0ms 
    engine:ws writing "42["message",{"body":"Test Post","from":"aDw0sZU_XZAAAE"}]" +0ms 
    engine:ws received "2" +4s 
    engine:socket packet +0ms 
    engine:socket got ping +0ms 
    engine:socket sending packet "pong" (undefined) +0ms 
    engine:socket flushing buffer to transport +0ms 
    engine:ws writing "3" +0ms 
    engine:ws received "2" +0ms 
    engine:socket packet +1ms 
    engine:socket got ping +0ms 
    engine:socket sending packet "pong" (undefined) +0ms 
    engine:socket flushing buffer to transport +0ms 
    engine:ws writing "3" +0ms 
    engine:ws received "2" +3s 
    engine:socket packet +0ms 
    engine:socket got ping +0ms 
    engine:socket sending packet "pong" (undefined) +0ms 
    engine:socket flushing buffer to transport +0ms 
    engine:ws writing "3" +0ms 
    engine:ws received "2" +1ms 
    engine:socket packet +0ms 
    engine:socket got ping +0ms 
    engine:socket sending packet "pong" (undefined) +0ms 
    engine:socket flushing buffer to transport +0ms 
+0

你爲什麼認爲它被髮送到'General'房間?你有什麼證據?你是否意識到一個套接字可以同時連接到多個房間,所以當你首先加入'General',然後到一個新房間時,套接字仍然在'General'房間裏。你沒有離開那個房間,所以它仍然在那個房間裏。 – jfriend00

+0

@ jfriend00 - 我更新了代碼以顯示我從服務器文件獲取的日誌,並且我還將套接字設置爲在創建新房間時離開當前房間。我相信,但可能是錯誤的,因爲在**消息**事件中,我發送了一條日誌,我相信告訴我當前消息發送時當前房間的名稱。當新房間事件下當前房間發生變化時,消息事件仍然使用在套接字連接時設置的默認常規房間。 –

+0

你是否意識到在你的代碼中'currentRoom'對每一個套接字都是唯一的?你的服務器上不只有一個'currentRoom',但每個套接字都有自己的'currentRoom'變量?所以,如果其他套接字發送「新房間」,那隻會爲該特定套接字更改「currentRoom」。您可以邏輯上認爲它是服務器端套接字對象的屬性,就好像它是'socket.currentRoom'一樣。所以,當套接字發送'message'時,該消息將被髮送到發送套接字的'currentRoom',而不是最後一個其他套接字設置的'currentRoom'。 – jfriend00

回答

1

實現以後,又有過在創建兩個插座,我意識到自己的問題的代碼位的地方坐下。原來我沒有在我的反應項目中正確嵌套Socket.IO。我有多個組件在客戶端上導入socket.io的實例。

(我曾在多個組件此行):

import io from 'socket.io-client'; 

原來使用這種進口將創建多個插座如果使用比項目一次。 (這是有道理的,不幸的是我花了很長時間才發現我的錯誤)。

如果有人在使用React框架時創建多個套接字時遇到問題,該解決方案很容易實現。首先,刪除組件上的socket.io導入,並將該語句移至父組件。在我的情況下,這是我的佈局組件。

Layout.js

import React from 'react'; 
import io from 'socket.io-client'; 

import Chat from './Chat/Chat'; 
import Info from './Info/Info'; 

const socket = io(); 

export default class Layout extends React.Component { 
    render(){ 
    return(
     <div class="wrapper"> 
     <h1>Rooms.io!</h1> 
     <Chat socket={socket}/> 
     <Info socket={socket}/> 
     </div> 
    ) 
    } 
} 

現在import語句是在一個父組件。您可以將套接字從父組件傳遞給任何子組件。如您所見,我將套接字傳遞給兩個組件Chat和Info。

在這些兒童組件中,你可以像使用React中的任何其他類型的道具一樣對待套接字。在我的示例中,目前,我將套接字變量設置爲等於套接字支柱(如在我的componentDidMount函數中所見)。

Chat.js

import React from 'react'; 

import Message from './Message'; 
import MessageList from './MessageList'; 

export default class Chat extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { messages: [] }; 
    } 

    componentDidMount(){ 
    const socket = this.props.socket; 
    socket.on('message', message => { 
     this.setState({ messages: [...this.state.messages, message] }); 
    }) 
    } 

    handleSubmit = event => { 
    const socket = this.props.socket; 
    const body = event.target.value 
    if(event.keyCode === 13 && body){ 
     const message = { 
     body, 
     from: 'Me' 
     } 
     this.setState({ messages: [...this.state.messages, message] }); 
     socket.emit('message', body) 
     event.target.value = ''; 
    } 
    } 

    render(){ 
    const messages = this.state.messages.map((message, index) => { 
     return <li key={index}>{message.from}: {message.body}</li> 
    }) 
    return(
     <div class="chat"> 
     <MessageList messages={messages}/> 
     <Message handleSubmit={this.handleSubmit}/> 
     </div> 
    ) 
    } 
} 

感謝@ jfriend00的幫助;我希望任何閱讀這篇文章的人都有一個愉快的一天,並且永遠不會忘記在React中嵌套套接字。乾杯!