【问题标题】:How to define all socket.io logic outside of app.js in a separate-file Express.js application?如何在单独的文件 Express.js 应用程序中定义 app.js 之外的所有 socket.io 逻辑?
【发布时间】:2022-01-08 02:21:19
【问题描述】:

期望的行为

socket.io initialisation docs 提供了这个示例,我目前在app.js 中使用:

import { createServer } from "http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server(httpServer, {
  // ...
});

io.on("connection", (socket) => {
  // ...
});

httpServer.listen(3000);

io 块之前还有三个对象需要在块内引用:

var logged_in_users = {};
var users_in_rooms = {};
var live_edits_occurring = {}; 

如您所见,一切都发生在app.js

我想重构 app.js 以便:

  1. io.on('connection') 功能块中的所有逻辑都在app.js 之外
  2. 可以在中间件文件中访问全局对象(logged_in_users 等)

实际行为

我收到此错误:

ReferenceError:logged_in_users 未定义

这意味着我无法从中间件文件访问logged_in_users

问题

我怎样才能让像logged_in_users 这样的对象可以全局访问?

以便它们可以被所有中间件文件引用和更新

app.locals 会是一个好方法吗?

// app.js  
app.locals.logged_in_users = {};
app.locals.users_in_rooms = {};
app.locals.live_edits_occurring = {}; 

我之前没有使用过app.locals,也不知道如何在中间件中访问app

我也不知道你是否可以从中间件更新app.locals,我需要这样做。

我的尝试

关注the docs on application structure,我有:

app.js

const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer);


const all_socketio_logic = require('./middleware/socketio/all_socketio_logic').all_socketio_logic;    
  
const on_connection = async (socket) => {
  all_socketio_logic(io, socket);
};

io.on('connection', on_connection);

/middleware/socketio/all_socketio_logic.js

import { heres_my_details } from './event_handler_heres_my_details';

const all_socketio_logic = (io, socket) => {

  // i want these available in the middleware defined below     
  var logged_in_users = {};
  var users_in_rooms = {};
  var live_edits_occurring = {};

  // sanity checks - all returning values - GOOD   
  console.log('socket.id is: ' + socket.id);
  console.log('logged_in_users is: ');
  console.log(logged_in_users);
  console.log('users_in_rooms is: ');
  console.log(users_in_rooms);
  console.log('live_edits_occurring is: ');
  console.log(live_edits_occurring);

  // this is being returned to browser - GOOD 
  socket.emit('heres_your_socket_id', socket.id);  

  // this middleware is running - GOOD  
  socket.on('heres_my_details', heres_my_details);

  /*

  i will add other event handlers here:  
  
  socket.on('another_event_01', another_event_01);
  socket.on('another_event_02', another_event_02);

  etc  

  */

};

export { all_socketio_logic };

/middleware/socketio/event_handler_heres_my_details.js

const heres_my_details = (data) => {
  
  console.log('heres_my_details:');
  console.log(data);
  
  var username = data.username;
  
  // if client is logged in
  if (username !== null) {
    var user_email = data.user_email;
  
    /* 
      if the logged_in_users object doesn't already contain 
      the clients socket id (as a property), add the socket 
      id property and define object username and user_email 
    */
  
    if (!logged_in_users.hasOwnProperty(socket.id)) {
      // the error is here - cannot access logged_in_users  
      logged_in_users[socket.id] = {};   
      logged_in_users[socket.id].username = username;
      logged_in_users[socket.id].user_email = user_email;
      console.log('logged_in_users AFTER ADDING new object:');
      console.log(logged_in_users);
    }
  }
};

export { heres_my_details };

我得到以下记录 - 好:

socket.id is: zhWMY0EpkNAWURN3AAAB
logged_in_users is:
{}
users_in_rooms is:
{}
live_edits_occurring is:
{}
heres_my_details:
{
  username: 'my username',
  user_email: 'my@email_address.com',
  logged_in: true
}

来自event_handler_heres_my_details.js 的错误 - 错误:

ReferenceError:logged_in_users 未定义

类似问题 (答案已过时或不完整)

Use socket.io in expressjs routes instead of in main server.js file

Node.js how to use socket.io in express route

Using socket.io with express 4 generator

NodeJS socket.io in a router page

Separating socket.io logic from app.js in feathersjs

How to move Socket.io io.on('connection') code another js file?

Separate Socket.io into app.js

Separating file server and socket.io logic in node.js

环境

节点 v16.13.0
快递:^4.17.1
socket.io: ^4.3.2
socket.io-client: ^4.3.2

【问题讨论】:

    标签: node.js express socket.io


    【解决方案1】:

    一种方法:

    app.js

    const express = require('express');
    const { createServer } = require('http');
    const app = express();
    const httpServer = createServer(app);
    
    const io = require('./ws.js')(httpServer);
    

    ws.js

    module.exports = function ws(httpServer) {
    
        var logged_in_users = {};
        var users_in_rooms = {};
        var live_edits_occurring = {}; 
    
        const { Server } = require('socket.io');
        const io = new Server(httpServer);
    
        httpServer.use(function(req, res, next){
            // attach io, etc. to every req object
            req.ws = {
                io,
                logged_in_users,
                users_in_rooms,
                live_edits_occurring
            };
            // call next to pass req to handler
            next();
        });
        
        io.on('connection', on_connection);
    
    };
    

    【讨论】:

    • 我很好奇。您使用的哪个版本的 Node 允许您向require('path', ...) 传递额外的参数?因为我很确定const io = require('./ws.js', httpServer); 没有做你希望的事情。 ;)
    • @RobRaisch 当然,我的错,应该是 const io = require('./ws.js')(httpServer); 感谢您指出这一点。
    猜你喜欢
    • 2018-06-28
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 2016-12-12
    • 2019-07-23
    • 2021-04-12
    相关资源
    最近更新 更多