【问题标题】:Getting socket.io namespace from anywhere in the project从项目中的任何地方获取 socket.io 命名空间
【发布时间】:2023-03-17 04:08:02
【问题描述】:

在我的 REST 调用和一些数据库插入之后,我想通过 socket.io 向前端发出一个新通知,如下所示:

socket.broadcast.emit('send notification', notification);

由于我正在执行此操作的函数是通过 REST 而不是通过 socket.io 触发的,因此我没有变量“socket”。

一开始我以为我可以像这样得到'io':

var io = require('socket.io') // or like: require('socket.io')(3000)

从这里我想我可以得到这样的命名空间:

var nsp = io.of('/notification-list');
nsp.on('connection', function (socket) { ... }

但是 io 似乎是未定义的(或者如果我将它与端口 3000 一起使用,我会得到 EADDRINUSE,因为显然 socket.io 已连接到 127.0.0.1:3000

这可能是一个非常愚蠢的问题,但由于我自己无法弄清楚:如何让socket 准备好在此函数中使用?任何帮助将不胜感激!


编辑:

我尝试了friend00的解决方案,但我仍然无法弄清楚如何做到这一点。

在我的server.js 中,我创建服务器并导入我的 socketIO 内容,如下所示:

var server =
http.createServer(app).listen(app.get('port'), function () {
});
require('./socketio_listener/socketIoListener')(server);

然后我的socketIoListener.js

var sockio = require("socket.io");
var io;

function initIO(server) {
    if (!server) { throw new Error("ERR"); }
    if (!io) {
        io = sockio.listen(server);
    }
    return io;
 }

module.exports.getIO = function () {
    if (!io) {  throw new Error("ERR"); }
    return io;
};

module.exports = function (server) {
io = initIO(server);

var nspNotification = io.of('/notification-list');
nspNotification.on('connection', function (socket) {
    socket.on('get notificationList', function (data) {
        notification.findNotifications(socket, data);
    });
    // ...
});

现在我尝试了我想通过 socket.io 发出一些东西的函数:

var io = require("socket.io").getIO();

我也试过了:

var ioServer = require('../socketio_listener/socketIoListener');
ioServer.getIO();

但我仍然总是得到:

TypeError: undefined is not a function

解决方案

我找到了解决方案,虽然我不太清楚之前为什么会出现问题:我将 module.exports.getIO = function () 移到了底部,现在它可以正常工作了。虽然我认为socketIoListener.js 中的位置并不重要,但它似乎确实如此。

【问题讨论】:

    标签: javascript node.js socket.io


    【解决方案1】:

    您必须通过导出或模块方法调用的某种组合将单个服务器端 io 变量共享给您的其他模块。

    一旦你像这样初始化了 socket.io 监听器:

    var io = require('socket.io').listen(server);
    

    您需要与其他想要使用socket.io 的模块共享特定的io 实例。具体分享方式取决于代码的结构以及您尝试将其分享到的位置。


    例如,你可以有一个模块来管理 io 的初始化:

    var sockio = require("socket.io");
    var io;
    
    // mysocketio.js
    // constructor function - should only be called once and passed the http server
    module.exports = function(server) {
        if (!server) {
            throw new Error("Must pass http server instance to mysocketio module constructor");
        }
        if (!io) {
            io = sockio.listen(server);
        }
        return io;
    };
    
    module.exports.getIO = function() {
        if (!io) {
            throw new Error("Must call constructor of mysocketio module before getIO()");
        }
        return io;
    };
    

    然后,在你用特定的 http 服务器初始化它的地方,你可以这样做:

    var io = require("mysocketio")(server);
    

    在您只想使用“已初始化”io 的其他模块中,您可以这样做:

    var io = require("mysocketio").getIO();
    

    【讨论】:

    • 我尝试了您的解决方案并将其添加到主题中,不幸的是它对我不起作用。你能告诉我我做错了什么吗?感谢您的帮助!
    • @Markus - 您需要自己的模块的路径:var io = require("path to your module").getIO();。我的答案有一个错字,我现在已经修正了。仅供参考,相对路径对于节点模块来说是很棘手的。因此,您需要确保正确找到所有模块。另外,我想知道您为什么将有用的错误消息取出并仅用 ERR 替换它们。这不会告诉使用它的人他们做错了什么或错误来自哪里。
    • 我只是为了回复而缩短了它,在我的代码中我仍然有错误消息。至于var io = require("path to your module").getIO();var ioServer = require('../socketio_listener/socketIoListener'); ioServer.getIO(); 应该这样做。至少这就是我通常从其他文件中导入内容的方式。路径是正确的,我只是仔细检查了它。还有什么我可能会错过的吗?
    • @Markus - 啊,我看到了一个问题。您必须在 module.exports.getIO = function() {...} 之前将分配移至 module.exports = function() {...},因为构造函数分配替换了整个 module.exports 对象,如果您先执行该分配,则会终止 getIO 分配。请参阅我的代码以了解正确的顺序。
    • 我自己发现了这个,想知道为什么它现在有效,感谢您的澄清和您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2016-08-16
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    相关资源
    最近更新 更多