javascript - 为什么脚本不正确地显示对象内容?
问题描述
这是我的客户端代码:
import {useEffect,useState} from 'react';
import io from 'socket.io-client';
import Peer from './Peer';
export default function TestMeeting(){
let peerName;
const [peerList,setPeerList]=useState({});
const [signalSocket,setSignalSocket]=useState(io.connect(process.env.REACT_APP_SOCKET_URL+"testMeeting", { transports: ['websocket'] }));
let sUsrAg = navigator.userAgent;
if (sUsrAg.indexOf("Edg")>-1){
peerName="Edge";
}else{
if (sUsrAg.indexOf("Chrome")>-1){
peerName="Chrome";
}else {
if (sUsrAg.indexOf("Firefox")>-1){
peerName="Firefox";
} else {
if (sUsrAg.indexOf("Safari")>-1){
peerName="Safari";
}
}
}
}
useEffect(()=>{
signalSocket.on("greeting",greeting=>{
let peer=new Peer(greeting.from,greeting.socketId);
let temp={...peerList};
temp[greeting.socketId]=peer;
setPeerList(temp);
})
signalSocket.on("newPeerAdded",(remotePeer)=>{
let peer=new Peer(remotePeer.from,remotePeer.socketId);
peerList[remotePeer.socketId]=peer;
let temp={...peerList};
temp[remotePeer.socketId]=peer;
setPeerList(temp);
signalSocket.emit("sayHi",{socketId:remotePeer.socketId,"peerName":peerName});
});
},[signalSocket,peerList,peerName])
let connect=()=>{
signalSocket.emit("newPeer",peerName);
}
console.log(peerList);
return(
<div>
<button onClick={connect}>Connect</button>
<div>
{
Object.keys(peerList).map((key,index) => (
<div key={index}>
{peerList[key].peerName()}
</div>
))
}
</div>
</div>
);
}
class Peer {
constructor(remotePeerName,remoteSocketId) {
let peerName=remotePeerName;
let socketId=remoteSocketId;
this.peerName=()=>{return peerName}
this.socketId=()=>{return socketId}
}
}
export default Peer;
这是我的服务器端代码:
class TestMeeting{
constructor(socket){
console.log("TestMeeting:Connection established");
socket.on('disconnect', function () {
console.log("TestSimplePeer:Disconnected");
});
socket.on("newPeer",(peerName)=>{
console.log("TestMeeting:newPeer event received.")
socket.broadcast.emit("newPeerAdded", {from:peerName,socketId:socket.id});
});
socket.on("sayHi",(sayHi)=>{
console.log("sayHi event received.");
socket.to(sayHi.socketId).emit("greeting",{from:sayHi.peerName,socketId:socket.id});
});
}
}
module.exports=TestMeeting;
这个怎么运作
当用户点击“连接”按钮时,它会通过服务器向其他节点发送“newPeer”事件。其他对等方将通过服务器向发送者响应带有套接字 ID 的“sayHi”事件。
测试用例
我打开了 3 个浏览器来测试这些代码,所以当我点击“连接”按钮时,我希望浏览器控制台应该显示以下内容:
Object { e_VLiK2A2ZrSS6uqAABn: {…} } TestMeeting.js:45
Object { e_VLiK2A2ZrSS6uqAABn: {…}, wjsYo70xzMWwkebkAABr: {…} } TestMeeting.js:45
但是,浏览器控制台显示以下内容:
Object { e_VLiK2A2ZrSS6uqAABn: {…} } TestMeeting.js:45
Object { wjsYo70xzMWwkebkAABr: {…} } TestMeeting.js:45
Object { e_VLiK2A2ZrSS6uqAABn: {…}, wjsYo70xzMWwkebkAABr: {…} } TestMeeting.js:45
你能告诉我发生了什么事吗?以及如何解决?
解决方案
经过几次尝试,我成功了:
客户端代码:
import { useEffect, useReducer } from "react";
import io from "socket.io-client";
export default function TestMeeting() {
let peerName;
let sUsrAg = navigator.userAgent;
if (sUsrAg.indexOf("Edg") > -1) {
peerName = "Edge";
} else {
if (sUsrAg.indexOf("Chrome") > -1) {
peerName = "Chrome";
} else {
if (sUsrAg.indexOf("Firefox") > -1) {
peerName = "Firefox";
} else {
if (sUsrAg.indexOf("Safari") > -1) {
peerName = "Safari";
}
}
}
}
let socket=io.connect(process.env.REACT_APP_SOCKET_URL + "testMeeting", {
transports: ["websocket"],
})
const initialState = {
peerList:{},
socket:socket
};
let reducer=(state,action)=>{
let result=null;
switch (action.type){
case "addPeer":
let temp={...state.peerList};
//console.log(state.peerList);
temp[action.peer.socketId]=action.peer;
result=result={...state,peerList:temp}
break;
case "initialPeerList":
result={...state,peerList:action.peerList}
break;
case "removePeer":
let temp1={...state.peerList};
delete temp1[action.socketId]
result=result={...state,peerList:temp1}
break;
default:
result=state;
break
}
return result;
}
useEffect(() => {
socket.emit("hi", peerName, (response) => {
console.log("=======================hi===============");
dispatch({type:"initialPeerList",peerList:response.peerList})
});
socket.on("newPeer", (peer) => {
dispatch({type:"addPeer",peer:peer})
});
socket.on("removePeer",(socketId)=>{
dispatch({type:"removePeer",socketId:socketId})
});
},[]);
const [state, dispatch] = useReducer(reducer, initialState);
console.log(state);
return(
<>
{Object.keys(state.peerList).map((key, index) => (
<div key={index}>{state.peerList[key].name}</div>
))}
</>
)
}
服务器端代码:
class TestMeeting{
constructor(){
let peerList={};
this.addPeer=(socket)=>{
socket.on('disconnect', function () {
let peer=peerList[socket.id];
console.log("TestSimplePeer:Disconnected");
if (peer){
console.log(peer.name+" leave the meeting.");
}
delete peerList[socket.id];
console.log("==================peer list===============");
console.log(peerList);
socket.broadcast.emit("removePeer",socket.id);
});
socket.on("hi",(peerName,calllBack)=>{
peerList[socket.id]={name:peerName,socketId:socket.id};
console.log("Received say hi from "+peerName+".");
socket.broadcast.emit("newPeer",peerList[socket.id]);
console.log("Broadcast newPeer ("+peerName+") to other peer.");
calllBack({"peerList":peerList})
})
}
}
}
module.exports=TestMeeting;