How does node module cache work with factory function?

I am confused about how Node require cache works with factory function.

Suppose that I have two files, moduleA.js contains a Express route:

const express = require('express');
const router = express.Router();
const { test, sideEffectA } = require('./moduleB.js');

router.get('/', async (req, res, next) => {
  console.log(testConfig());
  console.log(sideEffectA);  
});
module.exports = router;

moduleB.js:

let sideEffectA = 1;
const test = () => {
  let sideEffectB = 42;
  sideEffectA = sideEffectA + 1;
  sideEffectB = sideEffectB + 1;
  return {
    a: sideEffectA,
    sideEffectB
  }
};

module.exports = {
  test, sideEffectA
};

After I send three GET request to / I get the following results:

{ a: 2, sideEffectB: 43 }
1
{ a: 3, sideEffectB: 43 }
1
{ a: 4, sideEffectB: 43 }
1

The result of sideEffectB makes sense to me, because it is a factory function. But I don’t understand why is a increasing with each request while console.log(sideEffectA) always get the same result 1.
What exactly is happening when the router function is executed? Where does those two values a and console.log(sideEffectA) come from?

Update:

One more closely related question: if an async function is exported, will it only execute once with an resolved or rejected promise cached? Is there any diffence between

const foo = (input) => new Promise((resolve, reject) => {
  // Resolve or reject
}

module.exports = foo;

and

const bar = async (input) => {
  // Something here
}

module.exports = bar;

Thanks!

Answer

sideEffectA in the module.exports statement is a primitive value, referenced by its variable name during import [https://nodejs.org/en/knowledge/getting-started/what-is-require/]. When imported, a primitive JS number is assigned to sideEffectA in moduleA.js – a different variable to the closure in moduleB.js – which is why moduleB.js has incrementing sideEffectA values not mirrored in moduleA.js.

Leave a Reply

Your email address will not be published. Required fields are marked *