我一直在研究一个使用一些自定义Node.js模块的项目。我已经创建了一个'helpers'模块,可以帮助加载一些辅助方法:
/helpers/index.js:
var mutability = require('./mutability'),
cb = require('./cb'),
build = require('./build'),
userAgent = require('./userAgent'),
is = require('./is'),
query = require('./query'),
config = require('./config'),
_ = require('underscore')
module.exports = _.extend({
cb: cb,
build: build,
userAgent: userAgent,
is: is,
query: query,
config: config
}, mutability)
为了好玩,mutability.js
是:
'use strict'
module.exports = {
setReadOnly: function(obj, key) {
// whatever
return obj
},
setWritable: function(obj, key) {
// whatever
return obj
}
}
我的一个模块build
需要一个类来进行类型检查:
/helpers/build.js
'use strict'
var urljoin = require('url-join'),
config = require('./config'),
cb = require('./cb'),
Entity = require('../lib/entity'),
_ = require('underscore')
module.exports = {
url: function(options) {
return urljoin(
config.baseUrl,
options.client.orgId,
options.client.appId,
options.type, (typeof options.uuidOrName === 'string') ? options.uuidOrName : ""
)
},
GET: function(options) {
options.type = options.type || args[0] instanceof Entity ? args[0]._type : args[0]
options.query = options.query || args[0] instanceof Entity ? args[0] : undefined
return options
}
}
然后Entity
需要helpers
:
/lib/entity.js
'use strict'
var helpers = require('../helpers'),
ok = require('objectkit'),
_ = require('underscore')
var Entity = function(object) {
var self = this
_.extend(self, object)
helpers.setReadOnly(self, ['uuid'])
return self
}
module.exports = Entity
无论出于何种原因,当我使用Mocha运行时,我将helpers
注销为{}
并且Mocha会抛出:
Uncaught TypeError: helpers.setReadOnly is not a function
当我直接用/lib/entity.js
运行node
时,会打印出正确的模块。是什么赋予了?为什么Mocha会爆炸?
答案 0 :(得分:1)
您是正确的,问题是index.js
和entity.js
之间的循环依赖。
您的依赖关系图看起来像这样(带有规范化路径),其中每个箭头都是require
语句:
/helpers/index.js -> /helpers/build.js -> /lib/entity.js -> /helpers/index.js
当节点required
中的模块module.exports
初始化为空对象时。
如果你有循环依赖关系,那么在你的代码运行到实际设置module.exports = ...;
之前,这个默认对象可能会返回到另一个模块 (因为JavaScript是同步的) )。
这就是你的情况:/lib/entity.js
在index.js定义它/helpers/index.js
之前从module.exports = _.extend(...)
接收默认的导出对象。
要修复它,您需要确保将已返回的同一对象扩展为/lib/entity.js
,而不是将其替换为新实例:
// Extend `module.exports` instead of replacing it with a new object.
module.exports = _.extend(
module.exports,
{
cb: cb,
build: build,
userAgent: userAgent,
is: is,
query: query,
config: config
},
mutability
);
但是,如果可能的话,通常最好避免循环依赖。