使用Mocha时Catch-22递归节点模块爆炸 [英] Catch-22 recursive Node modules blowing up when using Mocha
问题描述
我一直在研究使用一些自定义Node.js模块的项目.我创建了一个帮助程序"模块,该模块可帮助加载一些帮助程序方法:
I've been working on a project that uses some custom Node.js modules. I've created a 'helpers' module that assists with loading some helper methods:
/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
,需要一个类来进行某种类型检查:
One of my modules, build
, requires a class to do some type checking:
/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引发:
For whatever reason, when I run this with Mocha, I get helpers
logging out as {}
and Mocha throws:
Uncaught TypeError: helpers.setReadOnly is not a function
当我直接使用node
运行/lib/entity.js
时,它将打印正确的模块.是什么赋予了?摩卡为何爆炸?
When I run /lib/entity.js
directly with node
, it prints the proper module. What gives? Why is Mocha blowing up?
推荐答案
您正确的问题是您在index.js
和entity.js
之间存在循环依赖关系.
You are correct that the issue is your circular dependency between index.js
and entity.js
.
您的依存关系图如下所示(带有标准化路径),其中每个箭头都是require
语句:
Your dependency graph looks like this (with normalised paths) where each arrow is a require
statement:
/helpers/index.js -> /helpers/build.js -> /lib/entity.js -> /helpers/index.js
当模块required
在节点module.exports
中被初始化为空对象时.
When a module is required
in Node module.exports
is initialised to an empty object.
当您具有循环依赖项时,有可能将此默认对象之前返回到另一个模块,因为您的代码已运行以实际设置module.exports = ...;
(因为JavaScript是同步的).
When you have a circular dependency then it's possible that this default object is returned to another module before your code has run to actually set module.exports = ...;
(because JavaScript is synchronous).
这就是您正在发生的情况:/lib/entity.js
在index.js定义它为module.exports = _.extend(...)
之前,已从/helpers/index.js
接收默认的导出对象.
This is what is happening in your case: /lib/entity.js
is receiving the default exports object from /helpers/index.js
before index.js has defined it's module.exports = _.extend(...)
.
要修复此问题,您需要确保扩展返回到/lib/entity.js
的同一对象,而不是用新的实例替换它:
To fix it you need to make sure that you extend the same object that has been returned to /lib/entity.js
, instead of replacing it with a new instance:
// 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
);
但是,通常最好避免循环依赖.
However, it's generally best to avoid circular dependencies if possible.
这篇关于使用Mocha时Catch-22递归节点模块爆炸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!