使用socket.io刷新浏览器时超出的最大调用堆栈大小



我一直在试图弄清楚为什么我的Node js服务器在刷新浏览器时总是崩溃。在初始连接到websocket时,一切工作正常,连接正常…然而,当我刷新浏览器时,我的服务器立即崩溃,出现这个错误…

E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:28
function hasBinary(obj, toJSON) {
^
RangeError: Maximum call stack size exceeded
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:28:19)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)
at hasBinary (E:Backnode_modulessocket.io-parserbuildcjsis-binary.js:49:63)

我想我已经把问题缩小到代码的断开部分,但是不能确定为什么它会崩溃,因为那里没有太多的逻辑,但它的最低限度…

server.js文件
export const io = new Server(4006, {
cors: {
origin: "http://192.168.0.19:5173",
credentials: true
}
})
const getSocketByUserId = (userId) => {
let socket = '';
for (let i = 0; i < clientSocketIds.length; i++) {
if (clientSocketIds[i].userId == userId) {
socket = clientSocketIds[i].socket;
break;
}
}
return socket;
}
io.use(async (socket, next) => {
console.log(socket.handshake.auth.userId)
if(socket.handshake.auth.userId) {
messageController.socketUserAuthentication(socket, next)
} else {
console.log('Already connected')
}
console.log('Authenticated')
}).on('connection', socket => {
console.log('conected')
messageController.storeConnectedUser(socket)
socket.on('disconnect', () => {
messageController.handleUserDisconnect(socket)
});
socket.on('create', function (data) {
console.log("create room")
socket.join(data.room);
let withSocket = getSocketByUserId(data.withUserId);
socket.broadcast.to(withSocket.id).emit("invite", { room: data })
});
socket.on('joinRoom', function (data) {
socket.join(data.room.room);
});
socket.on('message', function (data) {
socket.broadcast.to(data.room).emit('message', data);
})
});

message.controller.js

import userModel from '../user/user.model.js'
import emailModel from '../emails/email.model.js'
import calendarModel from '../calendar/calendar.model.js'
import { HttpException } from '../../utility/HttpException.utility.js'
import { validationResult } from 'express-validator'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import * as dotenv from 'dotenv'
import { logger } from '../../utility/logger.js'
import { isEmpty } from '../../utility/common.utility.js'
import { addHours, parseISO } from 'date-fns'
import _ from 'lodash'
import { io } from '../../server.js'
import { v4 as uuidv4 } from 'uuid'
import { user_type } from '../../utility/userRoles.utility.js'
dotenv.config()

class messageController {
constructor() {
this.connectedUsers = []
this.clientSocketIds = []
}
test = () => {
console.log('CLIENT SOCKET IDS',this.clientSocketIds)
console.log('CONNECTED USERS',this.connectedUsers)
}
getSocketByUserId = (userId) => {
let socket = ''
for (let i = 0; i < this.clientSocketIds.length; i++) {
if (clientSocketIds[i].userId == userId) {
socket = clientSocketIds[i].socket
break
}
}
return socket
}
socketUserAuthentication = async (socket, next) => {
try {
this.test()
console.log('Authenticate')
// console.log(socket.handshake.headers.bearer)
const authHeader = socket.handshake.auth.token
// const authHeader = socket.handshake.headers.bearer
const id = socket.handshake.auth.userId
console.log(authHeader)
console.log(id)
const bearer = 'Bearer '
if (!authHeader) {
console.log(authHeader)
return new HttpException(401, 'Access denied. No credentials sent!')
}
const token = authHeader.replace(bearer, '')
const secretKey = process.env.SECRET_JWT || ""
// Verify Token
const decoded = jwt.verify(token, secretKey)
const user = await userModel.findUser({ userId: decoded.user_id })
if (!user) {
return new HttpException(401, 'Authentication failed!')
}
// SOMETHING WITH ROLES
const ownerAuthorized = id == user.userId
if (!ownerAuthorized && roles.length && !roles.includes(user.user_type)) {
return new HttpException(401, 'Unauthorized')
}
socket.currentUser = user;
// console.log(socket.currentUser)
return next();
} catch (e) {
e.status = 401;
console.log(e)
next(e);
}
}
storeConnectedUser = (socket) => {
// , socket.currentUser.contacts
// io.emit('message', socket.currentUser.first_name)
// logger.info(`User has connected with the ID: ${socket.currentUser.userId}`)
this.clientSocketIds.push({ socket: socket, userId: socket.currentUser.userId, username: socket.currentUser.username })
this.connectedUsers = this.connectedUsers.filter(item => item.userId != socket.currentUser.userId)
this.connectedUsers.push({ username: socket.currentUser.username, userId: socket.currentUser.userId, uuid: uuidv4(), socket: socket })
// logger.info('User stored: ' + socket.currentUser.userId)
return socket
}
handleUserDisconnect = (socket) => {
// logger.info('User has disonnected: ' + socket.currentUser.userId)
this.connectedUsers = this.connectedUsers.filter(item => item.socketId != socket.id)
io.emit('updateUserList', this.connectedUsers)
return socket
}
}
export default new messageController

我通常期望在刷新时断开与服务器的连接,然后自动重新登录,但它会使服务器崩溃,直到重新启动才能加入。

*编辑删除行io.emit('updateUserList', this.connectedUsers)后,它似乎停止崩溃…

我打错了…this.connectedUsers = this.connectedUsers.filter(item => item.socketId != socket.id)而不是item.socketId,它应该是item.socket.id,我过滤了一个不存在的id,所以我猜当他们断开连接时,我试图发射这个。connectedUsers它是未定义的或者其他什么,然后在发送给用户时崩溃。

最新更新