Javascript NodeJ要求类返回{}

Javascript NodeJ要求类返回{},javascript,node.js,es6-modules,Javascript,Node.js,Es6 Modules,因此,我正在创建一个单例类,当我从我的server.js文件中需要它时,它可以正常工作,但当我从另一个文件中需要它时,它返回为未定义。我会尝试发布相关代码,但有些代码会因为工作而被删掉 server.js const createServices = require('./factories/services.js'); const injector = require('./lib/injector'); const Injector = new injector(); const serv

因此,我正在创建一个单例类,当我从我的
server.js
文件中需要它时,它可以正常工作,但当我从另一个文件中需要它时,它返回为未定义。我会尝试发布相关代码,但有些代码会因为工作而被删掉

server.js

const createServices = require('./factories/services.js');
const injector = require('./lib/injector');
const Injector = new injector();

const services = createServices(Injector, [require('./server/amq_listeners/fb_configs.listener'), require('./server/models/FBConfigs')]);

services.forEach((service, name) => {
  Injector.register(name, service);
});

// Start services
Injector.start();
const express=require('express');
const bodyParser=require('body-parser');
const path=require('path');
const http=require('http');
常量app=express();
const config=require('config');
const FBConfigsListener=require('./server/amq_listeners/fb_configs.listener');
const FBConfigs=require('./server/models/FBConfigs');
//用于与mongodb交互的Api文件
const api=require('./server/routes/api.routes');
//解析器
use(bodyParser.json());
use(bodyParser.urlencoded({extended:false}));
//角度距离输出文件夹
使用(express.static(path.join(uu dirname,'dist'));
//Api位置
应用程序使用('/api',api);
//将所有其他请求发送到angular
应用程序获取(“*”,(请求,请求)=>{
res.sendFile(path.join(uu dirname,'dist/index.html');
});
//设置端口
var port=config.get('webserver.port');
应用程序集(“端口”,端口);
const server=http.createServer(app);

server.listen(端口,()=>console.log(`Running on localhost:${port}`))它是由循环依赖项引起的。你应该避免使用或非常小心

在您的情况下,修复可能非常简单,移动行
var FBConfigs=require('../models/FBConfigs')来自侦听器,位于文件末尾,作为最后一行(是,即使在module.exports之后)


编辑:事实上,这可能是不够的,因为我更详细地检查了代码。由于您没有在FBConfig构造函数中使用侦听器,您可以创建方法
assignListener
,从该构造函数中删除
this.Listener
,然后在
server.js
中调用它,该方法将执行
this.Listener



或者是最后一个解决方案,也是“最佳实践”。不要导出实例。仅导出类。然后在server.js中,在需要这两个实例之后创建这些实例。

我建议您首先实例化依赖项,并将它们存储在某个对象中,然后将其传递给依赖类。结构可以是

工厂/服务.js

/*
 * Instantiates passed services and passes injector object to them
 */
module.exports = function createServices(injector, services) {
  return Object.entries(services)
    .reduce((aggregator, [name, serv]) => {
      const name_ = camelCase(name);

      aggregator.set(name_, new serv(injector));

      return aggregator;
  }, new Map());
};
lib/service.js

/**
 * Base class for classes need any injections
 */
module.exports = class Service {
  constructor(injector) {
    this.injector = injector;
  }

  get dependencies() {
    return this.injector.dependencies;
  }

  /*
   * Background jobs can be ran here
   */
  async startService() {}

  /*
   * Background jobs can be stopped here
   */
  async stopService() {}
};
lib/injector.js

const Service = require('./service');

/*
 * Contains all dependencies
 */
module.exports = class Injector {
  constructor() {
    this.services = new Map();
    this._dependencies = {};
  }

  has(name) {
    return this.services.has(name);
  }

  register(name, service) {
    if (this.has(name)) {
      throw new Error(`Service ${name} already exists`);
    }

    if (service instanceof Service === false) {
      throw new Error('Argument #2 should be an instance of Service');
    }

    this.services.set(name, service);
    this._dependencies[name] = service;
  }

  unregister(name) {
    if (! this.has(name)) {
      throw new Error(`Service ${name} not found`);
    }

    this.services.delete(name);
    delete this._dependencies[name];
  }

  get dependencies() {
    return { ...this._dependencies };
  }

  /*
   * Starts all registered services
   */
  async start() {
    for (let service of this.services.values()) {
      await service.startService();
    }
  }

  /*
   * Stops all registered services
   */
  async stop() {
    for (let service of this.services.values()) {
      await service.stopService();
    }
  }
};
然后在主文件中导入、初始化和绑定服务(不要忘记只导出一个类,而不是像现在这样导出一个对象)

server.js

const createServices = require('./factories/services.js');
const injector = require('./lib/injector');
const Injector = new injector();

const services = createServices(Injector, [require('./server/amq_listeners/fb_configs.listener'), require('./server/models/FBConfigs')]);

services.forEach((service, name) => {
  Injector.register(name, service);
});

// Start services
Injector.start();
将所需的类继承到
服务
类,您将可以访问那里的所有依赖项(不要忘记从构造函数调用
super()
)。像

模型/FBConfigs.js

const Service = require('../lib/service');    

class FBConfigs extends Service {
  constructor(injector) {
     super(injector);
     const { FBConfigsListener } = this.dependencies;
     ...your code here
  }

  async startService() {
    ...run bg job or init some connection
  }

  async stopService() {
    ...stop bg job or close some connection
  }
}

module.exports = FBConfigs;

您还可以将一些配置对象传递给
createServices
(我在这里没有包含它),键等于包含配置对象的服务名称和值,并将配置传递给相应的服务。

非常感谢。我要试一试@如果这个答案解决了你的问题,那么你可以考虑接受它作为正确的答案。没有问题。如果你需要一些澄清,请告诉我。如果我想让这个类成为一个单身学生,我该怎么办?这仍然有效吗?我不想继续创建新实例或FBConfigs或FBConfigsListener,因为它们在后台运行,从活动mq收集数据。这个解决方案是这样工作的吗?我想做我现在正在做的导出对象的事情吗?所有类在
createServices
函数中只初始化一次,它们的实例将存储在一个
Injector
对象中。只要您通过
Injector
实例访问它们,它们就会指向相同的
服务
实例。我将用启动/停止服务的可能性来补充答案。我只导出了该对象,因为我试图创建一个单例。但是我确实将require移到了module.exports下面,它开始工作了。但我会尝试上面贴的东西,这样我就可以遵循最佳实践。