Javascript 为socket.io导出HTTP服务器不工作

Javascript 为socket.io导出HTTP服务器不工作,javascript,node.js,express,socket.io,httpserver,Javascript,Node.js,Express,Socket.io,Httpserver,我有一个app.js 和一个server.js 如果我将服务器放在一个单独的文件中,套接字将不工作,但是如果我在app.js中启动服务器,套接字将工作。 我做错了什么?这里的问题是app.js加载server.js,server.js加载app.js时存在循环依赖关系。对于这种类型的代码,您不能这样做 它有一个问题,因为您试图从app.js中加载server.js,然后在加载server.js的过程中,它尝试加载app.js并获取其导出,但app.js尚未完成加载,因此甚至还没有返回其导出。因此

我有一个app.js

和一个server.js

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

这里的问题是app.js加载server.js,server.js加载app.js时存在循环依赖关系。对于这种类型的代码,您不能这样做

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

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

将一些代码分解为公共的第三个模块,每个模块都可以加载,并且只有其中一个模块可以加载另一个模块

与其让server.js加载app来获取app对象,不如让app.js在构造函数中将app对象传递给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对象通过构造函数推送到它。这可以防止循环依赖。

这两个文件相互需要,而且您也没有导出io实例为什么我需要导出io实例?我正在做一些测试,比如第三点。我需要将这两个文件分开。谢谢,你能解释一下,在构造函数中将app对象传递给server.js比在模块加载时执行更好吗。或者给我一个链接,解释在哪里?是的,谢谢,非常清楚,我正在尝试在结束问题之前是否一切正常。我在哪里可以了解更多关于这种构造函数技术的信息?对我来说是新的。@Mattia-它实际上只是导出一个在加载模块后可以调用的函数。它只允许您将一些共享变量传递给模块初始化代码,并将其移动到此函数中。这种技术通常被称为模块构造函数,尽管它实际上只是导出一个设计为在加载模块后立即调用的函数。我不知道关于这个主题有什么特别的参考。@Mattia-这里是关于这个主题的另一个答案:。那么module.exports是导出对象服务器而不是函数吗?
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;
// 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;
};