ExpressJS中Socket.io变量导出报错及数据流实现问题
解决Socket.io实例在路由模块中无法正确获取的问题
我来帮你排查下这两个错误,其实都是模块导出/导入的逻辑混乱导致的,咱们一步步拆解解决:
第一个错误:TypeError: Cannot read property 'sockets' of undefined
你在Nouvproj.js里用var Soc = require("../server"); var io = Soc.io;尝试获取io实例,但你的server.js根本没把io变量导出!Node.js模块默认不会暴露内部变量,除非你显式用module.exports导出。
不过更关键的是:你已经在server.js里把io作为参数传给了路由模块require("./routes/ajoutProj")(io),完全不需要再从server模块里导入,直接用传入的参数就行。
第二个错误:TypeError: Cannot read property 'apply' of undefined
你的Nouvproj.js里重复写了两次module.exports:
module.exports = function(io) { ... } module.exports = router;
后面的module.exports = router直接覆盖了前面的函数,导致server.js里调用require("./routes/ajoutProj")(io)时,其实拿到的是router对象,而不是一个可执行的函数,自然会报错。
修正后的完整代码
1. server.js(保持原有逻辑,无需修改)
... var server = app.listen(port); var io = require("socket.io").listen(server); var routerProj = require("./routes/ajoutProj")(io); // 这里调用函数传入io app.use("/api/proj", routerProj); ...
2. Nouvproj.js(修正导出逻辑,直接使用传入的io)
var express = require('express'); var router = express.Router(); // 导出一个接收io参数的函数,函数内部定义路由并返回router module.exports = function(io) { router.route("/projets") .post(function(req, res) { // 处理POST请求,比如保存数据后用io推送新内容 io.sockets.emit('new-proj', req.body); res.status(200).send('Projet ajouté'); }) .get(function(req, res) { // 处理GET请求,返回最新数据 res.status(200).send(/* 你的数据内容 */); }); return router; // 一定要返回router对象 };
为什么这样改?
- 路由模块通过函数导出的方式,直接接收
server.js传入的io实例,避免了跨模块引用的冗余和错误。 - 去掉了重复的
module.exports,确保server.js拿到的是可执行的函数,调用后返回正确的路由对象。 - 现在POST路由触发时,你可以用
io.sockets.emit()向所有连接的客户端推送新数据,GET路由也能正常返回最新内容,完美实现你要的数据流触发效果。
内容的提问来源于stack exchange,提问作者Hamza Haddad
相关产品推荐
相关产品推荐

