我一直在Node中遇到这个问题,每当我调用彼此的函数时,我的应用程序就会崩溃。
我已经做了这个最小的工作示例(因为它给我的错误):
启动模块
var module2 = require('./module2');
var data = 'data';
module2.doStuff(data);
单词数
var module3 = require('./module3');
function doStuff(data){
// Stuff happens to 'data'
module3.takeStuff(data);
}
function doSomethingElse(data){
console.log(data);
}
module.exports = {
doStuff: doStuff,
doSomethingElse: doSomethingElse
};
单词数
var module2 = require('./module2');
function takeStuff(data){
// Stuff happens to 'data'
module2.doSomethingElse(data); // I get the type error here
}
module.exports = {
takeStuff: takeStuff
};
我得到的错误是:
module2.doSomethingElse(data); // I get the type error here
^
TypeError: undefined is not a function
start module
调用module2
中的一个函数,最终调用module3
中的函数,该函数又调用module2
中的函数。
所有模块都是正确需要的,它会在module2
中找到第一种方法。
这里发生了什么?如果需要从模块中获取功能,那么如何处理这种模式呢?
修改
调试显示模块存在,但它与原型相比是空的。我的问题是为什么?在Node / JavaScript里面,这里发生了什么?
答案 0 :(得分:6)
这里的问题可以轻松解决,同时保持应用程序的结构(就循环引用而言,这很好)。
您只需要保留系统为模块提供的默认exports
对象。请勿使用module.exports = {...}
更改它。
以下内容应该有效:
var module2 = require('./module2');
var data = 'data';
module2.doStuff(data);
var module3 = require('./module3');
exports.doStuff = function doStuff(data){
// Stuff happens to 'data'
module3.takeStuff(data);
};
exports.doSomethingElse = function doSomethingElse(data){
console.log(data);
};
var module2 = require('./module2');
exports.takeStuff = function takeStuff(data){
// Stuff happens to 'data'
module2.doSomethingElse(data); // I get the type error here
};
我会尝试解释从起点的第一行发生的事情:
module.exports = {...}
module.exports = {...}
这里的问题是在第3点和第6点之间。在更改对它的引用之前,Module3正在接收module2(3)的导出(6)。
使用exports.method = ...
解决了问题,因为exports对象永远不会改变。
答案 1 :(得分:4)
你有一个循环引用,模块2依赖于模块3,模块3依赖于模块2,模块2依赖于模块3(依此类推)。因此,在尝试解析module 3
module 2
时,它无法完成,因为module 3
本身需要先解决。
来自https://nodejs.org/api/modules.html#modules_cycles:
当有循环的require()调用时,模块可能没有 在返回时完成执行。
为了防止无限循环,a.js的未完成副本 exports对象返回到b.js模块。
因此该模块可用,但不完整(这说明您只接收原型)。循环引用无论如何都是代码味道,尽量避免使用它:)
但是,如果您将模块2和3都作为依赖项放在启动模块中,那么无论如何都应该可以正常工作。
var module2 = require('./module2');
var module3 = require('./module3');
var data = 'data';
module2.doStuff(data);