require and module.exports : TypeError: X is not a function
require and module.exports : TypeError: X is not a function
文件结构:
server
├── controllers
│ ├── locationsController.js
│ ├── mainController.js
│ └── utilisateursController.js
├── models
│ ├── Locations.js
│ ├── Utilisateurs.js
| └── ...
├── routes.js
└── server.js
在 mainController
中,我有一个函数 isValid
来检查一个字符串,我把它放在那里是因为我想从 utilisateursController.js
和 locationsController.js
访问它。我将其导出如下:
mainController.js
const lc = require('./locationsController');
const uc = require('./utilisateursController');
// ...
module.exports = {
// Associate all models
associateAll: function () {
lc.associateLocations();
uc.associateUtilisateurs();
},
isValid: function(...fields) {
for (let i = 0; i < fields.length; i++)
if (fields[i] === undefined || fields[i] === null || fields[i] === '')
return false;
return true;
}
};
问题
我可以从 utilisateursController.js
访问函数 isValid
,但是当我尝试从 locationsController.js
执行相同的操作时,出现此错误:
(node:6461) UnhandledPromiseRejectionWarning: TypeError: mc.isValid is not a function
at exports.getAllTasks (.../server/controllers/locationsController.js:30:11)
代码
utilisateursController.js
从这个文件,我可以完美访问isValid
,没有错误。
const mc = require('./mainController');
// ...
exports.login = async function (req, res) {
let response = {
// ...
}
if (req.query == null) {
response.infoMsg = 'Query empty...';
res.send(response);
return;
}
const usernameInput = req.query.username;
const passwordInput = req.query.password;
if (!mc.isValid(usernameInput, passwordInput)) {
response.infoMsg = 'username or password is empty...'
res.send(response);
return;
}
// ...
}
locationsController.js
从这个文件中,我得到了上面提到的错误,我真的不知道为什么...
const mc = require('./mainController');
// ...
exports.getAllTasks = async function (req, res) {
let response = {
// ...
}
const usernameInput = req.params.username;
if (!mc.isValid(usernameInput)) {
response.infoMsg = 'No parameters given...';
res.send(response);
return;
}
// ...
}
我的想法
我认为这可能是因为要求的决议顺序...
调试器说的
utilisateursController.js
locationsController.js
我真的不知道是什么导致了这个问题...
问题是由 mainController
、utilisateursController
和 locationsController
之间的循环关系引起的。 utilisateursController
和 locationsController
都需要 mainController
,而 mainContoller
需要 utilisateursController
和 locationsController
。因此,Node.js 的 CommonsJS 风格的模块解析最终 运行 在你的至少一个(可能是两个)模块中使用占位符对象来导出其中一个模块的顶级代码其他模块。 (显然,在您的情况下,locationsController
获得了 mainController
导出的占位符。utilisateursController
可能也有,但不会尝试在顶层使用它。)
如果您避免在顶层使用 mc
,仅在稍后调用的函数中使用它,该占位符将在您需要之前被填充,一切都会好起来的。您引用的代码似乎只在函数中使用 mc
,但考虑到您遇到的错误,显然您的真实代码并非如此。
更多内容在 Node.js modules documentation's "Cycles" section。
旁注:原生 JavaScript 模块不会发生这种情况(通常称为 "ESM" 表示“ECMAScript Mmodules),因为即使存在循环依赖,它们也会在顶层模块代码获取 运行.
之前解决
文件结构:
server
├── controllers
│ ├── locationsController.js
│ ├── mainController.js
│ └── utilisateursController.js
├── models
│ ├── Locations.js
│ ├── Utilisateurs.js
| └── ...
├── routes.js
└── server.js
在 mainController
中,我有一个函数 isValid
来检查一个字符串,我把它放在那里是因为我想从 utilisateursController.js
和 locationsController.js
访问它。我将其导出如下:
mainController.js
const lc = require('./locationsController');
const uc = require('./utilisateursController');
// ...
module.exports = {
// Associate all models
associateAll: function () {
lc.associateLocations();
uc.associateUtilisateurs();
},
isValid: function(...fields) {
for (let i = 0; i < fields.length; i++)
if (fields[i] === undefined || fields[i] === null || fields[i] === '')
return false;
return true;
}
};
问题
我可以从 utilisateursController.js
访问函数 isValid
,但是当我尝试从 locationsController.js
执行相同的操作时,出现此错误:
(node:6461) UnhandledPromiseRejectionWarning: TypeError: mc.isValid is not a function
at exports.getAllTasks (.../server/controllers/locationsController.js:30:11)
代码
utilisateursController.js
从这个文件,我可以完美访问isValid
,没有错误。
const mc = require('./mainController');
// ...
exports.login = async function (req, res) {
let response = {
// ...
}
if (req.query == null) {
response.infoMsg = 'Query empty...';
res.send(response);
return;
}
const usernameInput = req.query.username;
const passwordInput = req.query.password;
if (!mc.isValid(usernameInput, passwordInput)) {
response.infoMsg = 'username or password is empty...'
res.send(response);
return;
}
// ...
}
locationsController.js
从这个文件中,我得到了上面提到的错误,我真的不知道为什么...
const mc = require('./mainController');
// ...
exports.getAllTasks = async function (req, res) {
let response = {
// ...
}
const usernameInput = req.params.username;
if (!mc.isValid(usernameInput)) {
response.infoMsg = 'No parameters given...';
res.send(response);
return;
}
// ...
}
我的想法
我认为这可能是因为要求的决议顺序...
调试器说的
utilisateursController.js
locationsController.js
我真的不知道是什么导致了这个问题...
问题是由 mainController
、utilisateursController
和 locationsController
之间的循环关系引起的。 utilisateursController
和 locationsController
都需要 mainController
,而 mainContoller
需要 utilisateursController
和 locationsController
。因此,Node.js 的 CommonsJS 风格的模块解析最终 运行 在你的至少一个(可能是两个)模块中使用占位符对象来导出其中一个模块的顶级代码其他模块。 (显然,在您的情况下,locationsController
获得了 mainController
导出的占位符。utilisateursController
可能也有,但不会尝试在顶层使用它。)
如果您避免在顶层使用 mc
,仅在稍后调用的函数中使用它,该占位符将在您需要之前被填充,一切都会好起来的。您引用的代码似乎只在函数中使用 mc
,但考虑到您遇到的错误,显然您的真实代码并非如此。
更多内容在 Node.js modules documentation's "Cycles" section。
旁注:原生 JavaScript 模块不会发生这种情况(通常称为 "ESM" 表示“ECMAScript Mmodules),因为即使存在循环依赖,它们也会在顶层模块代码获取 运行.
之前解决