0

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

尝试在文件顶部要求 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
    }
  }
}();
4

1 回答 1

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
    }
  }
};

要加载它,您需要从顶部向下传递服务器实例,在您的情况下是 to 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 有所不同,但总体思路可能仍然适用。

于 2014-08-21T21:55:25.513 回答