在 node.js 应用程序控制器中实施 socket.io

Implement socket.io in node.js application controller

下午好。我是 node.js 中套接字编程的新手,我需要在我的应用程序的控制器中实现 socket.io。我的架构如下:

启动服务器的文件是index.js

const express = require('express');
const app = express();
const port = 3000;
const socketRouter = require('./routes/socket')

app.use(express.json());
  
//Route
app.use('/socket', socketRouter);

app.listen(port, () => {
    console.log(`Server connection on  http://127.0.0.1:${port}`);  // Server Connnected
});

我定义路由的文件是socket.js

const { Router } = require('express');
const { showData } = require('../controllers/socket');

const router = Router();

router.post('/send-notification', showData);

module.exports = router;

我的控制器是:

const { response } = require('express');

const showData = (req, res = response) => {
    const notify = { data: req.body };
    //socket.emit('notification', notify); // Updates Live Notification
    res.send(notify);
}

module.exports={
    showData
}

我需要在此控制器中实现 socket.io 才能从中发出信号,但我无法让它工作。你能告诉我怎么做吗? 非常感谢

澄清:如果我在主文件中实现 socket.io 它可以工作,但我想要一些顺序和分开的东西。它是这样工作的:

const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

app.post('/send-notification', (req, res) => {
    const notify = { data: req.body };
    socket.emit('notification', notify); // Updates Live Notification
    res.send(notify);
});

const server = app.listen(port, () => {
    console.log(`Server connection on  http://127.0.0.1:${port}`);  // Server Connnected
});

const socket = require('socket.io')(server);

socket.on('connection', socket => {
    console.log('Socket: client connected');
});

如果您想通过以下方式分隔套接字消息和 REST 端点,则可以在其他文件中使用相同的 socketapp(如果您还需要公开 API)功能或您选择如何组织它。这是如何完成此操作的示例:

创建一个新文件,比方说controller1.js:

function initialize(socket, app) {
    socket.on('some-socket-message', socket => {
        // Whatever you want to do
    });
    
    app.get('/some-endpoint', (req, res) => {
        // whatever you want to do
    });
}


module.exports = {initialize}

然后将以下内容添加到您的 controller.js

const controller1 = require('path/to/controller1');

...

// At some point after socket and app have been defined
controller1.initalize(socket, app);

这将是根据需要分离控制器的基础,同时在所有控制器中仍使用相同的套接字连接和 API 端口。您也可以将 initialize 方法重构为不同的方法,但这将由您自己决定以及您希望如何命名函数等。它也不需要调用 initalize,那只是我喜欢的名字。

将您的 socket.io 代码移动到它自己的模块中,您可以在其中导出共享 socket.io 服务器实例的方法:

// local socketio.js module

const socketio = require('socket.io');

let io;
modules.exports = {
   init: function(server) {
       io = socketio(server);
       return io;
   },
   getIO: function() {
       if (!io) {
          throw new Error("Can't get io instance before calling .init()");
       }
       return io;
   }
}

然后,在您的主应用程序文件中初始化 socketio.js 模块:

const express = require('express');
const app = express();
const port = 3000;


app.use(express.json());
  
const server = app.listen(port, () => {
    console.log(`Server connection on  http://127.0.0.1:${port}`);  // Server Connnected
});

// initialize your local socket.io module
const sio = require('./socketio.js');
sio.init(server);

// now load socket.io dependent routes
// only after .init() has been called on socket.io module
const socketRouter = require('./routes/socket')
app.use('/socket', socketRouter);

然后,在任何你想访问 socket.io 服务器实例的地方,你可以 require("./socketio.js") 并使用 .getIO() 方法获取 socket.io 实例:

// use correct path to socketio.js depending upon where this module 
// is located in the file system
const io = require("../../socketio.js").getIO();

// some Express route in a controller
const showData = (req, res) => {
    const notify = { data: req.body };

    // send notification to all connected clients
    io.emit('notification', notify);
    res.send(notify);
};

module.exports= {
    showData
};

注意:服务器上典型的 socket.io 使用约定是使用 io 作为服务器实例,使用 socket 作为单独的客户端连接套接字实例。请不要尝试对两者都使用 socket。这清楚地表明 io.emit(...) 正在尝试发送到所有连接的客户端,而 socket.emit() 正在尝试发送到单个连接的客户端。

另请注意,如果您的路由是由浏览器本身发送表单 post 的表单 post 触发的,那么该特定客户端将不会收到 io.emit(...) done 的结果从该表单 post 路由,因为该浏览器将根据表单 post 的响应加载新网页,并将破坏其当前的 socket.io 连接。如果表单 post 完全通过 Javascript 使用 Ajax 调用完成,则该网页将保持活动状态并将接收 io.emit(...).

的结果