【发布时间】:2020-11-11 09:40:54
【问题描述】:
当前端在服务器之前加载时,我的套接字会产生问题, 我的问题是
1.我从多个客户端的cookies中得到相同的socketid
2.我只有一个客户端连接了服务器的多个socketid
3.当我遇到这个问题时,我的 API 调用将无法正常工作,并且我不会从我的数据库中获取任何数据
当我重新启动服务器以及使用不同的客户端多次刷新前端时,我也遇到了这个问题
我的服务器端代码
const mongoose = require("mongoose");
express = require("express");
app = express();
bodyParser = require("body-parser");
cookieParser = require("cookie-parser");
cors = require("cors");
user = require("./routes/user");
message = require("./routes/message");
http = require("http");
server = http.createServer(app);
io = require("socket.io")(server);
var userdata = require("./controllers/user");
mongoose
.connect(process.env.DATABASE, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log("DB CONNECTED");
})
.catch((err) => console.log(err));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(cors());
app.use(express.json());
app.use("/use", user);
app.use("/use", message);
let users = [];
io.on("connection", (socket) => {
socket.on("done", () => {
let userdata = require("./controllers/user");
console.log("connected");
userdata.userdata &&
users.push({ userid: userdata.userdata._id, socketid: socket.id });
console.log(users);
});
socket.broadcast.emit("message");
socket.on("more", function (c) {
console.log(c.a, c.b);
let d = users.find((s) => s.userid === c.b);
if (d) {
return io.to(d.socketid).emit("message", c);
}
});
socket.on("disconnect", () => {
console.log(socket.id);
if (users) {
for (let e = 0; users.length; e++) {
if (users[e] && users[e].socketid === socket.id) {
return users.splice(e, 1);
}
}
}
console.log(users);
return console.log("disconnected");
});
});
// app.use();
const port = process.env.PORT || 8000;
server.listen(port, () => {
console.log(`app is running at ${port}`);
});
我发现我的问题是由userdata引起的,当我删除了与userdata相关的所有内容后,即使重新加载服务器也没有任何问题。
这里的userdata来自一个叫做isSignedIn的中间件,这个中间件在这个网页的每个API调用之前被调用,所以userdata会经常更新通过前端代码。这是我的 isSignedIn 函数
exports.isSignedIn = async (req, res, next) => {
const header = req.headers["authorization"];
const token = header && header.split(" ")[1];
if (!token) return res.json("no token");
jwt.verify(token, "jsdhbcjsd", (err, User) => {
if (err) return res.json(`${err} not signedin`);
req.User = User;
exports.userdata = User;
next();
});
};
我尝试调用 isSignedIn() 而不是导入 userdata,这样会好很多,但我从 headers 收到错误>,所以我不能调用这个函数。
调用此函数时出现错误isSignedIn()
Promise {
<rejected> TypeError: Cannot read property 'headers' of undefined
at exports.isSignedIn (D:\message\backend\controllers\user.js:86:22)
它讲述了这一行
const header = req.headers["authorization"];
我确保只有在使用 await 调用 API 后才会在前端连接套接字,以便在连接到套接字之前更新 userdata。我已经在控制台中对其进行了测试,套接字调用 API 后才连接
async componentDidMount() {
//my API calls
await this.friends(token);
await this.findfriends(token);
//connect the socket
this.start();
this.recieve();
}}
我的前端代码
const client = require("socket.io-client");
var socket
export default class Home extends Component {
constructor(props) {
super(props);
this.start = this.start.bind(this);
this.send = this.send.bind(this);
this.recieve = this.recieve.bind(this);
this.friends= this.friends.bind(this);
this.findfriends= this.findfriends.bind(this);
}
start(){
socket=client("http://localhost:8000");
}
send(){
socket.emit("more", c)
}
recieve(){
socket.on("message", c)
}
async componentDidMount() {
//my API calls
await this.friends(token);
await this.findfriends(token);
//connect the socket
this.start();
this.recieve();
}}
render(){
return(my data)
}
}
【问题讨论】:
-
这个
let userdata = require("./controllers/user");在做什么?对于每个用户,您将获得与该语句完全相同的userdata。因此,当您执行users.push({ userid: userdata.userdata._id, socketid: socket.id });时,您每次都推送完全相同的userid属性。 -
另外,在这个
for (e = 0; users.length; ++e) {中,更改为for (let e = 0; e < users.length; ++e) {,这样您就不会在for循环中使用意外/隐式/未声明的全局,因此您的循环有适当的界限。 -
在阅读了您的 cmets 之后,我已经从服务器中删除了与用户数据相关的所有内容。刷新服务器时我没有遇到这个问题,只有当我删除时我才在前端获得相同的 socketid服务器重新加载之前的cookie。用户数据来自名为isSighnedin的中间件,该中间件在此页面的每个API之前调用,并且仅在客户端登录时才重定向到此页面。我正在导入用户数据,因为我不能调用它由于一些标头问题而在此处起作用。
-
我的 isSigned 函数
exports.isSignedIn = async (req, res, next) => { const header = req.headers["authorization"]; const token = header && header.split(" ")[1]; if (!token) return res.json("no token"); jwt.verify(token, "jsdhbcjsd", (err, User) => { if (err) return res.json('${err} not signedin'); req.User = User; exports.userdata = User; next(); }); }; -
多行代码在 cmets 中不可读。请使用“编辑”链接将代码添加到您的问题中,然后发布您更新问题的评论。
标签: node.js reactjs sockets websocket socket.io