【问题标题】:Exporting HTTP server for socket.io not working为 socket.io 导出 HTTP 服务器不起作用
【发布时间】:2018-07-13 06:02:19
【问题描述】:

我有一个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 内启动服务器,则套接字可以工作。 我做错了什么?

【问题讨论】:

  • 这两个文件相互需要,您也没有导出 io 实例
  • 为什么需要导出io 实例?我正在尝试做一些测试,如第 3 点here。我需要将这两个文件分开。

标签: javascript node.js express socket.io httpserver


【解决方案1】:

这里的问题是你有一个循环依赖,其中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.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 对象“推送”到它。这可以防止循环依赖。

【讨论】:

  • 谢谢,您能否更好地解释一下在构造函数中将 app 对象传递给 server.js,而不是尝试在模块加载时执行。 或者给我一个链接在哪里解释了吗?
  • 是的,非常感谢,我正在尝试在关闭问题之前是否一切正常。我在哪里可以了解有关此构造函数技术的更多信息?对我来说是新的。
  • @Mattia - 实际上只是导出一个可以在模块加载后调用的函数。它只允许您将一些共享变量传递给您在此函数内部移动的模块初始化代码。该技术通常被称为“模块构造函数”,尽管它实际上只是导出一个设计为在加载模块后立即调用的函数。我不知道有关该主题的任何特定参考。
  • @Mattia - 这是该主题的另一个答案:Node.js - use of module.exports as a constructor
  • module.exports 是导出对象server 而不是函数吗?
猜你喜欢
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 2015-04-30
  • 2016-01-16
相关资源
最近更新 更多