Search code examples
javascriptnode.jsside-effects

Why side-effect for my node.js code not worked


I'm beginner in NodeJS(version v21.6.1) and I tried to implement a code in multiple modules to understand side-effect concept in JavaScript but the code not worked, why?

// main.js

import './bootstrap.js';

console.log(` >>>>>>>>>>>>>> ${globalThis.someFunctionDep}`);
//  >>>>>>>>>>>>>> undefined

globalThis.someFunctionDep = true;

import './someModule.js';



// bootstrap.js

export default () => {
    globalThis.someFunctionDep = false;
    console.log("??????????????????");
}




// someModule.js

if (!Object.hasOwn(globalThis, "someFunctionDep") || !globalThis.someFunctionDep) {
    throw 'globalThis.someFunctionDep is not set';
}

I desired to automatically exported function in bootstrap.js module ran and add global variable someFunctionDep to context and accessible by others modules, but currently on the others this value is not available and is undefined.

Notice: If you answer is "function on the bootstrap.js file not ran automatically", please read this post .


Solution

  • I desired to automatically exported function in bootstrap.js module ran and add global variable someFunctionDep to context and accessible by others modules, but currently on the others this value is not available and is undefined.

    The issue is that you never call the function you're exporting from bootstrap.js. All you've done is export a function. main.js (or some other module, or bootstrap.js itself) would have to call that function to see its side-effects, just like any other function.

    You've mentioned this answer, saying it conflicts with what I'm saying above, but the difference is that in that answer there's a call to the function (print1 in that case), right there in the module exporting it; notice the print1(); call below the print2 function declaration. Your module doesn't have a call to the function, which is why the code in the function doesn't run.

    You need to add a call to your function somewhere. It could be in bootstrap.js although that would require changing how you export it:

    function x() {
        globalThis.someFunctionDep = false;
        console.log("??????????????????");
    }
    x();
    export default x;
    

    Or it could be in main.js:

    import fn from "./bootstrap.js":
    fn();
    

    Note that if it's in main.js, the call to fn() won't happen before someModule.js is loaded; see below for details on that.


    I think you're expecting the imports to happen when the import declarations are reached in the code. That isn't how JavaScript modules work. Instead, module dependencies are determined statically by looking at all of the import and export declarations in the interconnected modules, and then modules are loaded and their code executed in the appropriate order for the resulting module graph. Where the import declarations are in your modules' code relative to the step-by-step code in those modules is irrelevant.

    Your main.js code is functionally equivalent to:

    import './bootstrap.js';
    import './someModule.js';
    
    console.log(` >>>>>>>>>>>>>> ${globalThis.someFunctionDep}`);
    //  >>>>>>>>>>>>>> undefined
    
    globalThis.someFunctionDep = true;
    

    ...and the top-level code of both bootstrap.js and someModule.js will execute before the top-level code of main.js (because there are no cyclical relationships; it gets more complicated when there are).

    Finally: If you want to understand side-effects and module loading, it would probably be simpler just to use console.log to show when the top-level code in each module ran. For instance:

    main.js:

    import "./mod1.js";
    import "./mod2.js";
    
    console.log("main");
    

    mod1.js:

    console.log("mod1");
    

    mod2.js:

    console.log("mod2");
    

    With that, you'll see:

    mod1
    mod2
    main