'TypeError:undefined不是'跳转补间模块时的函数'

我不断收到这个问题,我的应用程序崩溃,每当我从另一个调用函数的节点。

我已经做了这个最小的工作示例(工作在它给我的错误):

启动模块

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的函数。

所有的模块都是正确的要求,它发现模块2中的第一个方法就好了。

这里发生了什么事,当需要从模块中得到一个函数的时候,这个模式会怎样呢?

编辑

debugging显示模块已经存在,但是除了原型之外,它是空的。 我的问题是为什么? Node / JavaScript里面发生了什么?

你有一个循环引用,模块2取决于模块3,依赖于模块2,依赖于模块3(依此类推)。 因此,在尝试解决module 3module 2 ,无法完成它,因为module 3本身需要先parsing。

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

这个问题可以很容易地修复,同时保持你的应用程序的结构(这是很好的,关于循环引用)。

您只需要保留由系统给您的模块的默认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); }; 

第3单元

 var module2 = require('./module2'); exports.takeStuff = function takeStuff(data){ // Stuff happens to 'data' module2.doSomethingElse(data); // I get the type error here }; 

说明

我会试着解释一下你的出发点是:

  1. 在start.js中,你需要module2,它还没有加载:来自module2.js的代码被执行
  2. 在module2.js中,您需要module3并且尚未加载:module3.js中的代码被执行
  3. 在module3.js中,您需要module2,并且已经加载:module2variables现在包含module2的exports对象。
  4. 执行module3的其余部分,并使用module.exports = {...}更改其导出对象
  5. 在module2.js中,module3variables现在包含来自module3的exports对象。
  6. 执行module2.js的其余部分,并使用module.exports = {...}更改其导出对象
  7. 在start.js中,module2variables现在包含来自module2的exports对象。

这里的问题是在第3点和第6点之间。在您更改引用(6)之前,Module3正在接收module2(3)的导出。 使用exports.method = ...解决了这个问题,因为exports对象不会改变。