gpt4 book ai didi

javascript - 每次发射都会触发 io.on 连接

转载 作者:搜寻专家 更新时间:2023-11-01 00:47:24 24 4
gpt4 key购买 nike

我的 socket.io 上的每个事件处理程序都首先调用 io.on 连接。例如-我进行了一次聊天,每次我发送一条消息(将其发送给所有客户端)时,它都会调用 io.on 连接,然后才向下移动到事件处理程序。

服务器文件

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


app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
let clients = 0;
io.on('connection', function (socket) {
clients++;
console.log('a user connected');
io.sockets.emit('User Connected', clients + ' clients connected');
socket.on('disconnect', function () {
clients--;
console.log('user disconnected');
io.sockets.emit('connected', clients + ' clients connected');
});

socket.on('msg sent', (msg) => {
console.log(msg, "new msg emit");
io.sockets.emit('msg sent', msg);
});
socket.on('user typing', (msg) => {
io.sockets.emit('user typing', msg);
});
});




http.listen(process.env.PORT || 8080, () => {
console.log('server started')
});

客户端聊天文件


import React, {Component} from 'react';

import socketIOClient from 'socket.io-client';
import Button from "react-bootstrap/Button";


class Chat extends Component {
constructor(props) {
super(props);
this.state = {endpoint: "localhost:8080", messages: [], newMsg: '', typing: '', connected: ''}
}

send = () => {
const socket = socketIOClient(this.state.endpoint);
socket.emit('msg sent', this.state.newMsg);
this.setState({typing: ''});
};

sentMsg = (event) => {
const socket = socketIOClient(this.state.endpoint);
socket.emit('user typing', 'User Typing');
this.setState({newMsg: event.target.value});
console.log(this.state.newMsg);
};


componentDidMount() {
const socket = socketIOClient(this.state.endpoint);
socket.on('msg sent', (msg) => {
console.log(msg, 'msg!!!');
this.setState({messages: [...this.state.messages, msg], typing: ''});

});
socket.on('user typing', (msg) => {
this.setState({typing: msg})
});
socket.on('User Connected', (msg) => {
this.setState({connected: msg});
})
};

renderMsg = () => {
if (this.state.messages.length > 0) {
return this.state.messages.map((msg) => {
return (<div className="border border-primary rounded m-2 p-1">{msg}</div>)
})
}
};

render() {
return (
<div className="container-fluid">
<div className="row chat p-2">
<div className="col-2 border-primary border m-1">
{this.state.connected}
</div>
<div className="col-9 border-danger border m-1 ">
{this.renderMsg()}
<br/>
{this.state.typing}
</div>
</div>
<div className="row">
<div className="fixed-bottom text-center">
<input type="text" className="col-6" onChange={this.sentMsg}/>
<Button className="m-1" onClick={() => {
this.send()
}}>Send</Button>
</div>

</div>

</div>
)
}

};

export default Chat;

希望只有当有新连接时,已连接的客户端计数器才会更新并加 1,但它会在我发送给它的每个事件中都这样做。

最佳答案

最近我们有同样的问题,每次客户端改变状态,都会创建一个新的到ws服务器的连接,导致多个websocket连接。我们所做的是@Chris Chen 的回答中的第 3 个

我们使用 web-worker 进行 socket.io ws 连接,但您只能在简单的 react 中实现它。毕竟思路是一样的。

function WrapContainer(props) {
const { provider, pairString } = props.state;
useEffect(() => {
const worker = new Worker('../../workers/blox_worker.js', {
type: 'module',
});
worker.postMessage({
marketPair: props.state.pairString,
provider: props.state.provider,
});

// Handling of websockets data here which basically event listener from worker
//...
// ..
return () => {
worker.terminate();
};
}, []);
}

您可以将 worker.terminate 替换为 socket.disconnect();代码中的return部分表示componentWillUnmount。这将确保当组件被销毁时,websocket 也将被杀死。如果您不终止 websocket,如果您使用 websocket 导航回组件,它也会创建另一个连接。因此,如果您希望与每个用户建立一致的 1 websocket 连接,那么添加这一点至关重要。

编辑:

进一步调查您的代码后,您似乎每次发送消息时都在重新创建 socket.io 客户端。客户端应该只是一个实例,因为每次您调用 socketIOClient 时,新的 ws 连接也将被创建,而且还应该对该实例进行发射。对于您的场景,一个更有效的用例是拥有一个将保存 socketio 客户端的变量。

import React, {Component} from 'react';

import socketIOClient from 'socket.io-client';
import Button from "react-bootstrap/Button";


class Chat extends Component {
constructor(props) {
super(props);
this.state = {endpoint: "localhost:8080", messages: [], newMsg: '', typing: '', connected: ''}
}

send = () => {
this.socket.emit('msg sent', this.state.newMsg);
this.setState({typing: ''});
}

sentMsg = (event) => {
this.socket.emit('user typing', 'User Typing');
this.setState({newMsg: event.target.value});
console.log(this.state.newMsg);
}


componentDidMount() {
this.socket = socketIOClient(this.state.endpoint);
this.socket.on('msg sent', (msg) => {
console.log(msg, 'msg!!!');
this.setState({messages: [...this.state.messages, msg], typing: ''});

});
this.socket.on('user typing', (msg) => {
this.setState({typing: msg})
});
this.socket.on('User Connected', (msg) => {
this.setState({connected: msg});
})
}

renderMsg = () => {
if (this.state.messages.length > 0) {
return this.state.messages.map((msg) => {
return (<div className="border border-primary rounded m-2 p-1">{msg}</div>);
})
}
};

render() {
return (
<div className="container-fluid">
<div className="row chat p-2">
<div className="col-2 border-primary border m-1">
{this.state.connected}
</div>
<div className="col-9 border-danger border m-1 ">
{this.renderMsg()}
<br/>
{this.state.typing}
</div>
</div>
<div className="row">
<div className="fixed-bottom text-center">
<input type="text" className="col-6" onChange={this.sentMsg}/>
<Button className="m-1" onClick={() => {
this.send()
}}>Send</Button>
</div>

</div>

</div>
)
}

};

关于javascript - 每次发射都会触发 io.on 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57879871/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com