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

Gem*_*tic 8 javascript typeerror node.js

我一直在Node中遇到这个问题,每当我调用彼此的函数时,我的应用程序就会崩溃.

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

启动模块

var module2 = require('./module2');

var data = 'data';

module2.doStuff(data);
Run Code Online (Sandbox Code Playgroud)

单词数

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
};
Run Code Online (Sandbox Code Playgroud)

单词数

var module2 = require('./module2');

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

module.exports = {
    takeStuff: takeStuff
};
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

module2.doSomethingElse(data); // I get the type error here
        ^
TypeError: undefined is not a function
Run Code Online (Sandbox Code Playgroud)

start module电话的功能module2,最终为函数调用中module3,这反过来又要求在一个函数module2.

所有模块都是正确需要的,它可以很好地找到第一种方法module2.

这里发生了什么,当一个人需要从模块中获得一个函数时,如何处理这种模式?

编辑

调试显示模块存在,但它与原型相比是空的.我的问题是为什么?在Node/JavaScript中,这里发生了什么?

Tar*_*gos 6

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

您只需要保留exports系统为模块提供的默认对象.不要改变它module.exports = {...}.

以下应该有效:

启动模块

var module2 = require('./module2');

var data = 'data';

module2.doStuff(data);
Run Code Online (Sandbox Code Playgroud)

第2单元

var module3 = require('./module3');

exports.doStuff = function doStuff(data){
    // Stuff happens to 'data'
    module3.takeStuff(data);
};

exports.doSomethingElse = function doSomethingElse(data){
    console.log(data);
};
Run Code Online (Sandbox Code Playgroud)

第3单元

var module2 = require('./module2');

exports.takeStuff = function takeStuff(data){
    // Stuff happens to 'data'
    module2.doSomethingElse(data); // I get the type error here
};
Run Code Online (Sandbox Code Playgroud)

说明

我将尝试解释从起点的第一行发生的事情:

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

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


Jus*_*ijn 4

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

来自https://nodejs.org/api/modules.html#modules_cycles

当存在循环 require() 调用时,模块在返回时可能尚未完成执行。

为了防止无限循环,a.js 导出对象的未完成副本将返回到 b.js 模块。

因此该模块可用,但不完整(这说明您只收到一个原型)。无论如何,循环引用都是一种代码味道,尽量避免它:)

但是,如果您将模块 2 和 3 作为依赖项放入启动模块中,那么它无论如何都应该可以工作。

var module2 = require('./module2');
var module3 = require('./module3');

var data = 'data';

module2.doStuff(data);
Run Code Online (Sandbox Code Playgroud)