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

时间:2014-08-21 19:55:57

标签: javascript node.js hapijs

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

当我尝试在文件顶部要求index.js时,我的foo-dao.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没有被曝光。

/hapi/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;

/hapi/modules/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//,
      }
    }
  ]
}();

/hapi/modules/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);
      });
    }
  }
}();

/hapi/modules/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
    }
  }
}();

1 个答案:

答案 0 :(得分:2)

  

我最终试图要求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的详细信息,我确定hapi.js不同,但一般的想法可能仍然适用。