[英]Socket.io in deeply nested Express Router
我正在嘗試將 socket.io 實例傳遞到 Express Routes。 目前我正在設置 socket.io 服務器,如他們的文檔所示。 要將對象傳遞到我使用的路線中,我使用app.set('io', io)
然后在路線中的路線const io = req.app.get('io')
中。 獲得 io 對象后,我只是向所有收聽用戶發送。 這適用於第一個請求,但第二次發出相同的請求時,會向每個客戶端發送兩個事件。 第三個請求發出數據三次,依此類推。
// App.js file
// Server imports
const app = require('express')(),
http = require('http').Server(app),
io = require('socket.io')(http),
session = require('express-session');
// Add socket.io to req for use in latter requests
app.set('io', io);
io.on('connection', (socket) => {
console.log('User has connected to socket.io');
socket.on('disconnect', () => {
console.log('User has disconnected');
});
});
// Route Setups
app.use('/api', require('./routes'));
http.listen(process.env.PORT, () => {
console.log(`Server running on port: ${process.env.PORT}`);
});
// Route index.js
const router = require('express').Router();
router.use('/project', require('./project/project'));
module.exports = router;
// Project Routes
const router = require('express').Router(),
Project = require('../../models/project');
// Route for creating new Projects
router.post('/', (req, res, next) => {
Project.createProject(req.body.item, (err, doc) => {
if(err) return next(err);
res.json({_id: doc._id, projectName: doc.projectName});
const io = req.app.get('io');
io.emit('project', {project: {
_id: doc._id,
client: doc.client,
jobId: doc.jobId,
projectName: doc.projectName,
eventDate: doc.eventDate,
dateModified: doc.dateModified,
eventLogo: doc.eventLogo
}});
})
});
// index.js
// Import React Standard components
// Import and setup BrowserRouter
import App from './components/App';
import io from 'socket.io-client';
const socket = io('http://192.168.1.2:8080');
ReactDOM.render(
<BrowserRouter>
<App socket={socket}/>
</BrowserRouter>
, document.getElementById('root'));
// Front End React File for displaying projects - App.js
// I cut down on some of the code to keep it simple.
import React, { Component } from 'react';
import NewProject from './NewProject';
export default class Projects extends Component {
state = {
projects: []
newProject: false
}
closeWindow = () => {
// Sets the state for new Project to true or false to show or hide the component
}
componentDidMount = () => {
// Fires mutiple times for each request made to update project or create new project
this.props.socket.on('project', ({project, index}) => {
console.log("DATA RECIEVED", project, index);
const projects = this.state.projects;
// If a project and index is sent, update an excising project
if(project !== undefined && index !== undefined) {
console.log('Project to ypdate: ',projects[index])
projects[index] = Object.keys(projects[index]).reduce((acc, key) => {
// Update all keys passed down from the server
}, {});
// If just a project is sent, add a new project
} else if(project !== undefined && index === undefined) {
projects.push(project);
// If just an index is sent, remove the project
} else if(index !== undefined) {
const projectIndex = this.props.projects.findIndex((item) => {
if(item._id === index) return true;
return null;
});
projects.splice(projectIndex, 1);
}
return this.setState({projects});
});
}
render() {
return [
this.state.newProject && <NewProject key="0" closeWindow={this.closeWindow} />
<main key="1">
// Display the projects
<button type="button" onClick={this.closeWindow}>New Project</button>
</main>
]
}
// Front End React File for Creating New Project
// NewProject.js
import React, { Component } from 'react';
export default class CreateProject extends Component {
state = {
client: '',
projectName: '',
jobId: '',
eventDate: '',
eventLogo: '',
completeForm: false
}
createProject = e => {
if(!this.state.completeForm) return;
fetch('/api/asset/project', {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(this.state)
})
.then(res => res.json())
.then(res => {
return this.props.closeWindow();
})
.catch(error => {// Handle Error})
}
render() {
return (
<div className="popup">
<form onSubmit={this.createProject}>
// All inputs for form.
</form>
</div>
)
}
}
我希望每個用戶都能恢復一次發出的數據,但根據發出請求的次數,他們會多次獲得數據。
非常感謝!!
請檢查 app.js 文件被調用了多少次。 如果它被多次調用,則有 io.on("connection".. 的多個事件。因此用戶多次接收數據。
對我有用的是將它添加到 Component Will Unmount
componentWillUnmount = () => {
this.props.socket.off('project');
}
我沒有意識到在卸載組件時事件偵聽器沒有自行分離。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.