Node.js报错TypeError: Cannot read properties of undefined (reading 'apply')求助
问题描述
我是Node.js新手,查了相关错误解答没解决问题。用socket.io开发多人游戏,用Express静态托管React应用时,大厅能正常显示,但游戏启动时服务器抛出TypeError: Cannot read properties of undefined (reading 'apply')错误。前后端分端口运行时应用完全正常,请问哪里操作错了?
相关代码
api.js
const express = require('express') const path = require('path') const api = express.Router() api.use(express.static(path.join(__dirname, "..", "public"))) module.exports = api
server.js
const http = require('http') const io = require('socket.io') const sockets = require('./sockets') const apiServer = require('./api') const httpServer = http.createServer(apiServer) const socketServer = io(httpServer, { cors: { origin: 'http://localhost:3000', methods: ["GET", "POST"] } }) const PORT = 4000 httpServer.listen(4000, () => { console.log(`Server is running on port: ${PORT}`) }) sockets.listen(socketServer)
日志信息
服务器启动及用户连接日志
Server is running on port: 4000 User connected CTmTWswPSNdfhhl2AAAB { playerData: { pid: '53f7bfaf-bbbb-496c-a666-f55a9d574054', avatar: 11, name: 'Nyah' }, players: 1 } User connected UkfcIX202fDXJ6caAAAD { playerData: { pid: '09b68067-cc0d-460d-b28c-21cde0c54862', avatar: 9, name: 'Walter' }, players: 2 }
游戏启动时错误日志
Game on Guys!!! /home/aimkeys/Development/projects/card-games/poker-server/node_modules/express/lib/router/index.js:646 return fn.apply(this, arguments); ^ TypeError: Cannot read properties of undefined (reading 'apply') at Immediate.<anonymous> (/home/aimkeys/Development/projects/card-games/poker-server/node_modules/express/lib/router/index.js:646:15) at processImmediate (node:internal/timers:468:21)
排查与解决思路
这个错误来自Express路由内部,说明某个请求匹配到了路由,但对应的处理函数fn是undefined。结合分端口运行正常、托管后报错的现象,问题大概率出在静态托管的路由匹配逻辑和前端请求路径的变化上:
错误根源分析
分端口时,前端在3000端口,所有请求后端的接口/Socket事件都是明确指向4000端口;但托管后前端和后端同端口,前端可能用了相对路径请求某些未定义的后端接口,Express找不到对应的处理函数,就会触发这个错误。另外,用express.Router()来托管静态文件的方式不规范,Router是用来分组API路由的,静态资源托管应该直接挂在Express实例上,避免路由匹配冲突。具体修复步骤
- 调整静态托管方式:把api.js改成直接创建Express实例,而不是用Router。修改后的api.js:
const express = require('express') const path = require('path') const api = express() // 先定义API路由(如果有的话),再托管静态文件 // api.use('/api', ...) 这里可以加你的API路由 // 托管静态文件,确保所有静态资源请求都被处理 api.use(express.static(path.join(__dirname, "..", "public"))) module.exports = api - 检查前端请求路径:游戏启动时打开浏览器开发者工具,查看网络请求,确认是否有请求了不存在的路径(比如
/game/start这类后端没定义的路由)。如果有,要么在后端补充对应的路由处理,要么修改前端用Socket.io事件代替HTTP请求。 - 确认Socket.io路径不冲突:确保Socket.io的默认路径
/socket.io没有被Express的静态托管或其他路由覆盖,当前配置里这个应该没问题,但可以在socket.io初始化时显式指定path: '/socket.io'来确认。
- 调整静态托管方式:把api.js改成直接创建Express实例,而不是用Router。修改后的api.js:
验证修改
重启服务器后测试游戏启动流程,看错误是否消失。如果还有问题,检查sockets.js里的逻辑,是否有代码误触发了HTTP请求而不是Socket事件。
内容的提问来源于stack exchange,提问作者aimkeys mwaura
相关产品推荐
相关产品推荐

