在暴露之前需要模块的节点导致未定义

Node requiring module before it's exposed is causing undefined

本文关键字:节点 未定义 模块 暴露      更新时间:2023-09-26

我最终试图在我的foo-dao.js文件中要求var server = require('../../index.js');,以便我可以访问hapi服务器插件,而不必通过hapi request对象从控制器到dao。

这个问题可以在我的foo-dao.js方法的注释中看到,当我试图在文件的顶部要求index.js时。

我认为问题是因为在我的index.js中,它需要。/modules文件夹,它需要。/modules/foo/foo-routes.js,它需要。/modules/foo/foo-ctrl.js,它需要。/modules/foo/foo-dao.js。

这是一个简化的视觉

./modules/index.js -> ./modules/foo/foo-routes.js -> ./modules/foo/foo-ctrl.js -> ./modules/foo/foo-dao.js -> ./modules/index.js <——问题出在这里,因为index.js中的SERVER变量还没有被暴露。

/哈皮神/index.js

/**
 * Hapi.js server.
 *
 * @type {exports}
 */
var Hapi = require('hapi');
var modules = require('./modules');
// Instantiate the server
var server = new Hapi.Server('0.0.0.0', 4445, {cors: true, debug: {request: ['error']}});
...
/**
 * Add all the modules within the modules folder
 */
for(var route in modules) {
  server.route(modules[route]);
}
/**
 * Expose the server's methods when used as a require statement
 *
 * @type {exports.server}
 */
module.exports = server;

/哈皮神/模块/foo/foo-routes.js

var Joi = require('Joi');
var fooController = require('./foo-ctrl');
module.exports = function() {
  return [
    {
      method: 'GET',
      path: '/api/foo',
      config: {
        handler: fooController.foo//,
      }
    }
  ]
}();

/哈皮神/模块/foo/foo-ctrl.js

var fooDao = require('./foo-dao');
module.exports = function() {
  return {
    foo: function foo(req, reply) {
      fooDao.findFoo(function(err, data) {
        if (err) {
          return reply(Boom.badImplementation(err));
        }
        reply(data);
      });
    }
  }
}();

/哈皮神/模块/foo/foo-dao.js

var server = require('../../index.js');  //  WHEN I REQUIRE THE FILE HERE, IT'S UNDEFINED, PROBABLY BECAUSE THE server OBJECT HAS NOT BEEN EXPOSED YET
console.log('server = ');
console.log(server);
module.exports = function() {
  return {
    findFoo: function findFoo(callback) {
      var server = require('../../index.js');  //  WHEN I REQUIRE THE FILE HERE, IT'S ACTUALLY DEFINED, PROBABLY BECAUSE THE server OBJECT HAS BEEN EXPOSED BY THIS POINT. I DON'T WANT TO HAVE TO REQUIRE INDEX.JS IN EVERY SINGLE FUNCTION THOUGH. HOW CAN I CIRCUMVENT THIS PROBLEM?
      ... get data and return it in the callback
    }
  }
}();

我最终试图要求var server = require('../../index.js');在我的foo-dao.js文件中,这样我就可以访问hapi服务器插件,而不必通过hapi请求对象从控制器传递给dao。

这是一个非常明显的CommonJS系统试图拯救你的糟糕设计。不要让一个子模块知道更高的相关父模型。它使子模块不可重用,并将其与包含它的应用程序强耦合,这与您想要的相反。深层次的、可重用的模块应该通过选项和请求对象来获得它们需要的东西,而不是通过要求更高层次的应用抽象。

这是你在foo-dao.js中想要做的,至少作为解决循环要求问题的第一步。但除此之外,我认为你需要更广泛地改变你的代码结构,使它干净。

module.exports = function makeDao(server) {
  return {
    findFoo: function findFoo(callback) {
      //now via closure you have permanent access to the server,
      //without being coupled so tightly to it's exact filesystem location
    }
  }
};

要加载它,需要从顶部向下传递服务器实例,在您的示例中是传递到modules

var server = new Hapi.Server('0.0.0.0', 4445, {cors: true, debug: {request: ['error']}});
var modules = require('./modules')(server);

这将使你的模块代码更容易测试(依赖注入)和重用。

我在express_code_structure存储库中详细阐述了我的总体方法。特别注意app实例是如何向下传递到路由的。具体的工作方式在express4中有所改变,我相信happy .js也会有所不同,但一般的思路可能仍然适用。