javascript - require and module.exports : TypeError: X is not a function - Stack Overflow

admin2025-04-17  0

File structure :

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

Problem

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)

Code

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

  // ...

}

What I think

I think it is maybe because of the order of the resolutions of the requires...

What the debugger says

utilisateursController.js

locationsController.js

I really don't know what is causing this porblem...

File structure :

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

Problem

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)

Code

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

  // ...

}

What I think

I think it is maybe because of the order of the resolutions of the requires...

What the debugger says

utilisateursController.js

locationsController.js

I really don't know what is causing this porblem...

Share Improve this question asked Apr 1, 2019 at 14:08 David AlvarezDavid Alvarez 1,28613 silver badges23 bronze badges 1
  • 1 Please have a read through the help's minimal reproducible example section. Going through the process of creating a minimal, but plete, example is an important part of debugging, and (if you don't figure it out), asking a question. – T.J. Crowder Commented Apr 1, 2019 at 14:21
Add a ment  | 

1 Answer 1

Reset to default 8

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.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1744885913a272532.html

最新回复(0)