如何在控制器内部使用 socketio?
How to use socketio inside controllers?
我有一个使用 Reactjs、Redux、Nodejs 创建的应用程序,MongoDB。我在后端创建了 socketio。
server.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
const routes = require('./routes/api/routes');
var server = require('http').Server(app);
const io = require('./socket').init(server);
app.use(express.json());
require('dotenv').config();
mongoose.connect(process.env.MONGO_DB).then(console.log('connected'));
const corsOptions = {
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus: 200,
};
app.use(cors(corsOptions));
app.use(routes);
if (
process.env.NODE_ENV === 'production' ||
process.env.NODE_ENV === 'staging'
) {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
io.on('connection', (socket) => {
console.log('New client connected');
socket.on('disconnect', () => {
console.log('Client disconnected');
});
});
server.listen(process.env.PORT || 5000, () => {
console.log('socket.io server started on port 5000');
});
socket.js
let io;
module.exports = {
init: (httpServer) => {
return (io = require('socket.io')(httpServer, {
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'POST'],
},
}));
},
getIO: () => {
if (!io) {
throw new Error('Socket.io is not initialized');
}
return io;
},
};
在 controller.js 中,我正在 mongodb 中创建新项目,并且还使用了 socketio。我正在发出我创建的新项目。看起来是这样
controller.js
const createTeam = async (req, res) => {
const userId = req.user.id;
const newItem = new Item({
name: req.body.name,
owner: userId,
});
await newItem.save((err, data) => {
if (err) {
console.log(err);
return res.status(500).json({
message: 'Server Error',
});
}
});
await newItem.populate({
path: 'owner',
model: User,
select: 'name',
});
await User.findByIdAndUpdate(
userId,
{ $push: { teams: newItem } },
{ new: true }
);
io.getIO().emit('team', {
action: 'creating',
team: newItem,
});
res.json(newItem);
};
在前端,我正在使用 socket.io-client 监听 socketio 服务器。在我的 App.js 中,当我 console.log(data) 时,我可以看到来自后端的数据。在此阶段之前,我的应用程序运行完美。我可以从 socketio 获取数据,我可以看到连接的新客户端。但是当我使用 dispatch 发送数据时,我的应用程序开始向数据库添加无限的新项目。看看我的App.js
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { AppNavbar } from './components/AppNavbar';
import { TeamList } from './components/TeamList';
import { loadUser } from './Store/Actions/AuthActions';
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { io } from 'socket.io-client';
import { addItems } from './Store/Actions/itemActions';
function App() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadUser());
const socket = io('http://localhost:5000');
socket.on('team', (data) => {
if (data.action === 'creating') {
dispatch(addItems(data.team));
}
// console.log(data);
});
}, []);
return (
<div className="App">
<AppNavbar />
<TeamList />
</div>
);
}
export default App;
我在redux端的itemAction也是这样
export const addItems = (input) => (dispatch, getState) => {
axios
.post('/api/items/createTeam', input, tokenConfig(getState))
.then((res) =>
dispatch({
type: ADD_ITEM,
payload: res.data,
})
)
.catch((err) =>
dispatch(
returnErrors(err.response.data, err.response.status, 'GET_ERRORS')
)
);
};
我的问题是如何在实现 socketio 后停止对 api 的无限调用。如何有效地停止死循环?
无限循环源于未调度“类型:ADD_ITEM”once.This 问题导致您的 itemAction 总是会在每次之后调度“类型:ADD_ITEM”和有效负载然后你的反应会 re-render 一次又一次地翻页。
您应该摆脱在 addItems 函数内的调度操作,并仅在 App.js 文件中的 useEffect 内调度您的操作。
您的代码片段在 App.js 中应如下所示:
useEffect(() => {
//...
const socket = openSocket('http://localhost:5000');
socket.on('postsChannel', (data) => {
if (data.action === 'creating') {
dispatch({ type: ADD_ITEM, payload: data.team });
}
});
}, [dispatch]);
我有一个使用 Reactjs、Redux、Nodejs 创建的应用程序,MongoDB。我在后端创建了 socketio。
server.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
const routes = require('./routes/api/routes');
var server = require('http').Server(app);
const io = require('./socket').init(server);
app.use(express.json());
require('dotenv').config();
mongoose.connect(process.env.MONGO_DB).then(console.log('connected'));
const corsOptions = {
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus: 200,
};
app.use(cors(corsOptions));
app.use(routes);
if (
process.env.NODE_ENV === 'production' ||
process.env.NODE_ENV === 'staging'
) {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
io.on('connection', (socket) => {
console.log('New client connected');
socket.on('disconnect', () => {
console.log('Client disconnected');
});
});
server.listen(process.env.PORT || 5000, () => {
console.log('socket.io server started on port 5000');
});
socket.js
let io;
module.exports = {
init: (httpServer) => {
return (io = require('socket.io')(httpServer, {
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'POST'],
},
}));
},
getIO: () => {
if (!io) {
throw new Error('Socket.io is not initialized');
}
return io;
},
};
在 controller.js 中,我正在 mongodb 中创建新项目,并且还使用了 socketio。我正在发出我创建的新项目。看起来是这样
controller.js
const createTeam = async (req, res) => {
const userId = req.user.id;
const newItem = new Item({
name: req.body.name,
owner: userId,
});
await newItem.save((err, data) => {
if (err) {
console.log(err);
return res.status(500).json({
message: 'Server Error',
});
}
});
await newItem.populate({
path: 'owner',
model: User,
select: 'name',
});
await User.findByIdAndUpdate(
userId,
{ $push: { teams: newItem } },
{ new: true }
);
io.getIO().emit('team', {
action: 'creating',
team: newItem,
});
res.json(newItem);
};
在前端,我正在使用 socket.io-client 监听 socketio 服务器。在我的 App.js 中,当我 console.log(data) 时,我可以看到来自后端的数据。在此阶段之前,我的应用程序运行完美。我可以从 socketio 获取数据,我可以看到连接的新客户端。但是当我使用 dispatch 发送数据时,我的应用程序开始向数据库添加无限的新项目。看看我的App.js
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { AppNavbar } from './components/AppNavbar';
import { TeamList } from './components/TeamList';
import { loadUser } from './Store/Actions/AuthActions';
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { io } from 'socket.io-client';
import { addItems } from './Store/Actions/itemActions';
function App() {
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadUser());
const socket = io('http://localhost:5000');
socket.on('team', (data) => {
if (data.action === 'creating') {
dispatch(addItems(data.team));
}
// console.log(data);
});
}, []);
return (
<div className="App">
<AppNavbar />
<TeamList />
</div>
);
}
export default App;
我在redux端的itemAction也是这样
export const addItems = (input) => (dispatch, getState) => {
axios
.post('/api/items/createTeam', input, tokenConfig(getState))
.then((res) =>
dispatch({
type: ADD_ITEM,
payload: res.data,
})
)
.catch((err) =>
dispatch(
returnErrors(err.response.data, err.response.status, 'GET_ERRORS')
)
);
};
我的问题是如何在实现 socketio 后停止对 api 的无限调用。如何有效地停止死循环?
无限循环源于未调度“类型:ADD_ITEM”once.This 问题导致您的 itemAction 总是会在每次之后调度“类型:ADD_ITEM”和有效负载然后你的反应会 re-render 一次又一次地翻页。
您应该摆脱在 addItems 函数内的调度操作,并仅在 App.js 文件中的 useEffect 内调度您的操作。
您的代码片段在 App.js 中应如下所示:
useEffect(() => {
//...
const socket = openSocket('http://localhost:5000');
socket.on('postsChannel', (data) => {
if (data.action === 'creating') {
dispatch({ type: ADD_ITEM, payload: data.team });
}
});
}, [dispatch]);