Accessing non-existent property of module.exports inside circular dependency NodeJS

35k views Asked by At

Im having some issues when using module.exports inside NodeJS, and I've followed multiple guides, and im almost certain Im doing it right. I have to scripts, main.js and event.js. Im trying to share a function from main.js to event.js, but its not working. Here is the code:

Main.js

function Scan(){
    if(fs.readdirSync('./events/').length === 0){
        console.log(colors.yellow('Events Folder Empty, Skipping Scan'))
    } else {
        var events = fs.readdirSync('./events/').filter(file => file.endsWith('.json'))
                for(const file of events){
                    let rawdata = fs.readFileSync('./events/' + file);
                    let cJSON = JSON.parse(rawdata);
                }
                events.sort()
                tevent = events[0]
                StartAlerter()
                }
}

module.exports = { Scan };

Event.js

const main = require('../main')

main.Scan;

This returns the error:

(node:19292) Warning: Accessing non-existent property 'Scan' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

What am I doing wrong?

4

There are 4 answers

2
gjoe On BEST ANSWER

Problem solved, heres what I did differently:

module.exports = { Scan };

Is declared before the Scan function is defined, like so:

module.exports = { Scan };
function Scan(){
//Code
}

Then in event.js, I wrote

const main = require('../main')

As it is now a module, and can be used with the require() function. Then to execute the funciton in event.js, I write

main.Scan()

To execute it.

2
Barrios On

better try :

module.exports = Scan;

0
Joel On

I discovered that the arrangement had no effect in the error.

I simply changed the way I exported the function from the Main.js

from:

module.exports = { Scan };

to:

exports.Scan = Scan

And in Event.js, I was able to access the file like this

const main = require("./Main.js");
let result = main.Scan();

This solved my problem, I hope it helps another developer

0
Wege On

I am gonna answer it using a simple example, like in this case below:

  1. File A has 3 functions to process database activity: function addDB, updateDB, and delData;
  2. File B has 2 functions to process User activity on smartphone: function addHistory, and editHistory;

Function updateDB in file A is calling function editHis in file B, and function editHistory is calling function updateDB in file A. This is what we called circular-dependency. And we need to prevent it by only giving output of state from editHistory and the rest will be processed inside file A.

//ORIGINAL FUNCTIONS which caused CIRCULAR DEPENDENCY
function updateDB() {
  //process update function here
  //call function in fileB
  const history = require("fileB.js");
  await history.editHistory(data).then((output) => {
    if(output["message"] === "success"){
      response = {
        state: 1,
        message: "success",
      };
    }
  });
  return response; 
}

//THIS is the WRONG ONE
function editHistory() {
  //process function to edit History here
  //call function in fileA
  const file = require("fileA.js");
  await file.updateDB(data).then((output) => { //You should not call it here
    if(output["message"] === "success") {
      output = {
        state: 1,
        message: "success",
      };
    }
  });
  return output; 
}

//==================================================//
//THE FIX
function updateDB() {
  //process function here
  const history = require("fileB.js");
  await history.editHistory(data).then((output) => {
    if(output["message"] === "success"){
      await updateDB(data).then((output) => {
        response = {
          state: 1,
          message: "success",
        };
      });
    } else {
      log("Error");
    }
  });
  return response; 
}

function editHistory() {
  //process function to edit History here
  // No more calling to function inside the file A
  output = {
    state: 1,
    message: "success",
  };
  return output; 
}