本文将介绍如何使用 Socket.io 实现一个在线投票系统,包括前端和后端的代码实现,旨在提供一个详细且有深度的学习指导,并帮助读者快速上手 Socket.io。
什么是 Socket.io?
Socket.io 是一个实时通信库,它允许在客户端和服务器之间双向通信。Socket.io 可以在不同的浏览器和设备上创建实时的,基于事件的应用程序,使得远程数据交换更加容易。
在线投票系统的功能和需求
在线投票系统是一个非常常见的实时交互应用,通过它可以实现让多个用户同时参与某一项决策或评选活动,包括但不限于:
- 创建、发布、管理投票;
- 观看投票实时更新状态;
- 用户在线实时投票。
在这个示例项目中,我们将实现以下功能:
- 用户可以创建、编辑和删除投票;
- 所有在线用户将同步观看投票状态;
- 所有在线用户将能够实时投票。
应用架构
为了实现以上功能,我们需要实现一个应用架构,如下图所示:

从图中可以看出,我们需要实现以下三个主要组件:
- Express.js 服务器端应用程序(Server Application):它会处理所有来自客户端的网络请求,并根据业务逻辑发送响应。在这个示例项目中,我们将使用 Express.js 作为后端服务器。它将使用 Socket.io 库来处理实时通信。
- Socket.io 服务器端应用程序(Socket Server Application):它将建立一个实时通信网络,连接所有在线客户端。在这个示例项目中,我们将使用 Socket.io 库作为后端服务器。
- 客户端应用程序(Client Application):它由一些 JavaScript 代码构成,并运行在客户端的浏览器中。在这个示例项目中,我们将使用 React.js 作为前端应用程序。
代码实现
后端代码实现
首先,我们需要借助 npm 安装 Express.js、Socket.io 和相关依赖:
npm init npm install express socket.io cors
然后,我们创建一个 server.js 文件,作为后端服务器的入口:
// www.javascriptcn.com code example
const express = require('express');
const http = require('http');
const socketIO = require('socket.io');
const cors = require('cors');
const PORT = process.env.PORT || 3000;
const INDEX = '/index.html';
const app = express()
.use(cors())
.use((req, res) => res.sendFile(INDEX, {root: __dirname}));
const server = http.createServer(app);
const io = socketIO(server, {
cors: {
origin: '*',
}
});
io.on('connection', (socket) => {
console.log(`Socket ${socket.id} connected.`);
});
server.listen(PORT, () => console.log(`Server started on port ${PORT}`));上述代码创建了一个 Express.js 应用,然后将其作为 Socket.io 应用程序的参数传递给 socketIO 函数,并通过 http.createServer 函数创建一个 HTTP 服务器实例。最后,io.on 函数用于监听 connection 事件,这样每当有客户端连接到服务器时,就会创建一个新的 socket 实例,并打印出它的 ID。
接下来,我们将为服务器实现一些自定义的事件和行为。这些自定义事件用于处理应用程序中的各种情况,例如创建投票、更新投票状态,以及投票等等。修改后的 server.js 文件如下所示:
// www.javascriptcn.com code example
const express = require('express');
const http = require('http');
const socketIO = require('socket.io');
const cors = require('cors');
const PORT = process.env.PORT || 3000;
const INDEX = '/index.html';
const app = express()
.use(cors())
.use((req, res) => res.sendFile(INDEX, {root: __dirname}));
const server = http.createServer(app);
const io = socketIO(server, {
cors: {
origin: '*',
}
});
let polls = [];
const findPoll = (id) => {
return polls.find(poll => poll.id === id);
};
const deletePoll = (id) => {
polls = polls.filter(poll => poll.id !== id);
};
io.on('connection', (socket) => {
console.log(`Socket ${socket.id} connected.`);
socket.on('createPoll', (data) => {
const newPoll = {
id: Date.now().toString(),
title: data.title,
options: data.options.map(option => ({text: option, count: 0}))
};
polls.push(newPoll);
io.emit('pollsUpdated', polls);
});
socket.on('vote', (data) => {
const poll = findPoll(data.pollId);
const option = poll.options.find(option => option.text === data.optionText);
option.count++;
io.emit(`pollUpdated:${poll.id}`, poll);
});
socket.on('deletePoll', (id) => {
deletePoll(id);
io.emit('pollsUpdated', polls);
});
socket.on('disconnect', () => {
console.log(`Socket ${socket.id} disconnected.`);
});
});
server.listen(PORT, () => console.log(`Server started on port ${PORT}`));上述代码创建了一个 polls 变量,用于存储所有投票,然后定义了三个自定义事件:createPoll、vote 和 deletePoll。这些事件对应应用程序中的“创建投票”、“更新投票状态”和“删除投票”操作。
现在,我们已经完成了服务器端的代码实现。
前端代码实现
接下来,我们将使用 React.js 实现客户端应用程序。首先,安装 React.js 和 Socket.io:
npm install react react-dom socket.io-client
然后,创建一个名为 App.js 的文件,放置以下代码:
// www.javascriptcn.com code example
import React, {useState, useEffect} from 'react';
import io from 'socket.io-client';
const socket = io('http://localhost:3000');
function App() {
const [polls, setPolls] = useState([]);
const [title, setTitle] = useState('');
const [options, setOptions] = useState(['', '']);
useEffect(() => {
socket.on('pollsUpdated', (data) => {
setPolls(data);
});
}, []);
const createPoll = () => {
socket.emit('createPoll', {title, options});
setTitle('');
setOptions(['', '']);
};
const vote = (pollId, optionText) => {
socket.emit('vote', {pollId, optionText});
};
const deletePoll = (id) => {
socket.emit('deletePoll', id);
};
return (
<div className="App">
<h1>在线投票系统</h1>
<input
type="text"
placeholder="输入标题"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<table>
<tbody>
{polls.map(poll =>
<tr key={poll.id}>
<td>
<strong>{poll.title}</strong>
<button onClick={() => deletePoll(poll.id)}>删除</button>
</td>
{poll.options.map((option, index) =>
<td key={index}>
<button onClick={() => vote(poll.id, option.text)}>{option.text}</button>
<div>投票数:{option.count}</div>
</td>
)}
</tr>
)}
</tbody>
</table>
<button onClick={createPoll}>创建投票</button>
<button onClick={() => setOptions(options.concat(''))}>添加选项</button>
</div>
);
}
export default App;上述代码定义了一个 App 组件,包含一些状态和自定义事件。在 useEffect 中,我们监听 pollsUpdated 事件,以便在客户端获取到新的投票数据时更新状态。在几个自定义事件中,我们将相应 emit 请求发送到服务器,以便对数据进行操作。
运行示例代码
现在,我们已经完成了示例项目的后端和前端代码实现。我们只需要使用以下命令启动它们:
node server.js npm start
最终的结果如下图所示:

恭喜你,你已经成功实现了一个在线投票系统,并使用 Socket.io 实现了实时通信。这对于想要学习 Socket.io 或实现类似应用的开发者来说是一次很好的实践。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d01ddbe46428fe9ecbdb82