对套接字IO的响应:广播不起作用

问题描述 投票:2回答:1

我正在使用Socket IO进行游戏。每个房间都使用通讯渠道。当玩家下注时,我想发送给对方。但是,播放器也正在接收该消息

这是我的React组件

import React, {useState, useEffect} from "react"
import { useParams, Redirect } from 'react-router-dom'
import socketIOClient from "socket.io-client";

import { BACKEND_URL } from  '../../constants'

export default function Room() {
    const { id } = useParams(); 

    const [room, setRoom] = useState({});
    const [game,setGame] = useState({
        state: 'waiting',
        payload: {},
    })

    const [price, setPrice] = useState(10);

    /**
     * This function verify if the room exist
     * If exists, set a variable with its properties
     * If doesn't exist, return to the initial page
     */
    useEffect(() => {
        fetch(`${BACKEND_URL}/rooms`)
            .then((response) => response.json())
            .then(rooms => {
                let auxRoom = undefined;
                rooms.map((room) => {
                    if(room.id == id) {
                        auxRoom = room;
                    }
                })
                setRoom(auxRoom)
            })
    }, []);

    /**
     * This function set the begin of the game
     * Define that the player is waiting 
     * And wait the signal to begin the game
     */
    useEffect(() => {
        const socket = socketIOClient(BACKEND_URL);
        socket.emit("waiting room", id);
        socket.on("start room", () => {
            setGame({
                state: 'playing',
                payload: {}
            })

            socket.on('opponent made bet', (price) => {
                console.log("opponent")
                console.log(price)
            })

        })
    }, [])

    function toBet(event) {
        const socket = socketIOClient(BACKEND_URL);
        event.preventDefault();
        //Emiting that the player made a bet
        socket.emit("make a bet", id, price);
    }

    return(
        <div>
            { !room ? //If the room doesn't exist, should be redirect
                <Redirect to="/"/>
                : null }

            Estamos na sala {id}!

            {
                game.state == 'playing' ?
                <div className="game">
                    <div className="scoreboard">
                    </div>
                    <div className="arena">
                        <label>Escolha o preço do petróleo:</label>
                        <select value={price} onChange={(event) => setPrice(event.target.value)}>
                            <option value="10">10</option>
                            <option value="20">20</option>
                            <option value="30">30</option>
                        </select>
                        <button onClick={toBet}>Apostar</button>
                    </div> 
                </div>
                : null
            }

        </div>
    )
}

这是我的后端

const app = require("express")();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

let rooms = [
    {
        id: 1,
        name: 'Room 1',
        owner: 'Bruna',
        amountOfPlayers: 0,
    },
    {
        id: 2,
        name: 'Room 2',
        owner: 'Amancio',
        amountOfPlayers: 0,
    }
]

function indexRoom(id) {
    for(let i = 0; i < rooms.length; i++)
        if(rooms[i].id == id)
            return i;
}

app.get('/rooms', (req, res) => {
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.json(rooms)
})

io.on('connection', (socket) => {

    /**
     * Socket that is responsible for start the game
     * When two players connect, the game begins
     */
    socket.on('waiting room', id => {
        //A player get in the room
        socket.join(id); 
        let index = indexRoom(id);

        if(index != undefined) {
            rooms[index].amountOfPlayers++;
            //When are two players, should start the game
            if(rooms[index].amountOfPlayers >= 2) {
                io.to(id).emit('start room');
            }
        }
    })

    socket.on('make a bet', (id, price) => {
        socket.broadcast.to(id).emit('opponent made bet', price)
    })

})

http.listen(8080, () => {
})

[玩家下注时,它应该发出'下注',只有对手才可以下注。但这不是它的工作方式。在单击按钮一次后,这是两个播放器的控制台:在单击按钮的播放器的控制台中,它被打印了两次!!!我不想打印,仅在对手中打印(即打印一次)

After a bet

我是Socket.io的初学者,很抱歉,这是一个基本概念。

javascript reactjs sockets
1个回答
0
投票

我认为问题可能出在以下代码上

useEffect(() => {
        const socket = socketIOClient(BACKEND_URL);
        socket.emit("waiting room", id);
        socket.on("start room", () => {
            setGame({
                state: 'playing',
                payload: {}
            })

            socket.on('opponent made bet', (price) => {
                console.log("opponent")
                console.log(price)
            })

        })
    }, [])

您必须将const套接字声明移到useEffect挂钩之外。所以

const socket = socketIOClient(BACKEND_URL);
useEffect(() => {
        socket.emit("waiting room", id);
        socket.on("start room", () => {
            setGame({
                state: 'playing',
                payload: {}
            })

            socket.on('opponent made bet', (price) => {
                console.log("opponent")
                console.log(price)
            })

        })
    }, [])
© www.soinside.com 2019 - 2024. All rights reserved.