server
├── controllers
│ ├── locationsController.js
│ ├── mainController.js
│ └── utilisateursController.js
├── models
│ ├── Locations.js
│ ├── Utilisateurs.js
| └── ...
├── routes.js
└── server.js
In mainController
I have a function isValid
to check a string, I put it there because I want to access it from both utilisateursController.js
and locationsController.js
. I export it as follow :
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;
}
};
I can access the function isValid
from utilisateursController.js
, but when I try to do the same from locationsController.js
, I have this error:
(node:6461) UnhandledPromiseRejectionWarning: TypeError: mc.isValid is not a function
at exports.getAllTasks (.../server/controllers/locationsController.js:30:11)
utilisateursController.js
From this file, I can perfectly access isValid
, there is no error.
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
From this file, I get the error mentioned above, and I really don't know why...
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;
}
// ...
}
I think it is maybe because of the order of the resolutions of the requires...
utilisateursController.js
locationsController.js
I really don't know what is causing this porblem...
The problem is caused by the fact you have a circular relationship between mainController
, utilisateursController
, and locationsController
. Both utilisateursController
and locationsController
require mainController
, and mainContoller
requires both utilisateursController
and locationsController
. As a result, Node.js's CommonsJS-style module resolution ends up running the top-level code in at least one (probably both) of your modules with a placeholder object for the exports of one of the other modules. (Apparently, in your case, locationsController
gets a placeholder for mainController
's exports. utilisateursController
probably does, too, but doesn't try to use it at the top level.)
If you avoid using mc
at the top level, only using it in functions called later, that placeholder will get filled in before you need it and all will be well. The code you've quoted seems to only use mc
within a function, but given the error you're getting, apparently that's not true of your real code.
More in the Node.js modules documentation's "Cycles" section.
Side note: This doesn't happen with native JavaScript modules (often called "ESM" for "ECMAScript Modules), because even when there are circular dependencies, they're resolved before the top-level module code gets run.