为 socket.io 导出 HTTP 服务器无效

Exporting HTTP server for socket.io not working

我有一个app.js

const express = require('express');
const app = express();
const server = require('./server.js');

// app.use
const io = require('socket.io').listen(server);
io.on('connection', function (socket) {
   ...
});

module.exports = app;

还有一个server.js

const app = require('./app');
const server = app.listen(5000 || process.env.PORT, () => {
    console.log('App listening on port 5000!');
})
module.exports = server;

如果我将服务器放在一个单独的文件中,则套接字无法正常工作,但如果我在 app.js 中启动服务器,则套接字可以正常工作。 我做错了什么?

这里的问题是您有一个循环依赖,其中 app.js 正在加载 server.js 并且 server.js 正在加载 app.js。您不能为此类代码执行此操作。

它有一个问题,因为您试图从 app.js 中加载 server.js,然后在加载 server.js 的过程中,它尝试加载 app.js并获取它的导出,但是 app.js 还没有完成加载,因此甚至还没有返回它的导出。因此,加载程序认为没有导出或识别循环请求(我不确定是哪个),但在任何一种情况下,app.js 的导出都不起作用,因为循环要求。

有几种不同的方法可以解决这个问题。最常见的两种方式是:

  1. 将一些代码分解成一个通用的第三个模块,每个模块都可以加载,并且只有一个可以加载另一个。

  2. 与其让 server.js 加载 app 来获取 app 对象,不如让 app.jsapp 对象传递给 server.js 在构造函数中,而不是尝试在模块加载时执行。

以下是构造函数想法的工作原理:

app.js

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

// load server.js and call it's constructor, passing the app object
// that module constructor function will return the server object
const server = require('./server.js')(app);

// app.use
const io = require('socket.io').listen(server);
io.on('connection', function (socket) {
   ...
});

module.exports = app;

server.js

// export constructor function that must be called to initialize this module
module.exports = function(app) {

    const server = app.listen(5000 || process.env.PORT, () => {
        console.log('App listening on port 5000!');
    });
    return server;
};

因此,不是 server.js 尝试加载 app.js 模块来获取 app 对象,app 对象是 "pushed"构造函数。这可以防止循环依赖。