Experiments

On circular dependencies in Javascript

April 4, 2019

Interesting dialog captured from our company’s Slack chat.

  • F S [9:10 PM] Error: Unexpected value 'undefined' imported by the module 'AuthPagesModule'

    For anyone who doesn’t knows, this is Angular’s way to say" “Hey! You have a circular dependency on your modules!"

  • J D [9:11 PM] thats a javascript feature I’m sure that has cost many millions of hours of developer time over the years… Its even better in vanilla javascript with require style, you just get an undefined object and it silently continues. const library = require('library'); < library here will just be undefined and you are left up to your own to realize its a circular dependency (edited)

  • A O [9:18 PM] I think it’s “ok” because the circular dependency will be available eventually The same thing happens in python

  • J D [9:19 PM] available eventually?

  • A R [9:20 PM] Angular has a way to deal with that, forwardRef

  • A O [9:20 PM] Module internals are undefined because the interpreter hasn’t yet gotten that far

  • A O [9:25 PM] Say you had

    // a.js
    const B = require('./b');
    exports.prop = 'foo';
    
    // b.js
    const A = require('./a');
    console.log(A.prop) // undefined
    
    setInterval(() => {
      console.log(A.prop) // 'foo'
    }, 1000);
    

    Since the log is deferred by a second the interpreter has finished its job and prop is defiend

  • Mark Safronov [6 minutes ago] @AO What is your entry point? This example is quite meaningless without one. I just made the files a.js and b.js as you described and then made entry point script named circular.js, which does just require b.js:

    require('./b');
    

    If I run node circular.js it will print me ‘foo’ every 1 second indefinitely.

    If I run node b.js it will print me ‘foo’ every 1 second indefinitely.

    If I run node a.js it will print me ‘undefined’ once then ‘foo’ every 1 second indefinitely.

    I think circular dependency like that will break your application no matter whether Node.js module system finished parsing the module or not.

Previous: FPS in console (!)