How do I resolve a circular dependency in ES6 modu

2020-05-03 10:01发布

I want to write something like this inside my src/core/Chessman.js file:

import King from './chessmen/King'

class Chessman {
  static factory(side, quality) {
    switch(quality) {
      case 'king' : return new King(side) break
      // ... other qualities
    }

    constructor(side) { this.side = side }

    cast(position, ref) { }

    run(position, startRef, endRef) {}
  }

and inside my src/core/chessmen/King.js file:

import Chessman from '../Chessman'

class King extends Chessman {

  constructor(side) {
    super(side)
    this.iterative = false // true for Queens, Rooks and Bishop
    this.directions = [
      'up', 'up+right', 'right', 'right+down', 
      'down', 'down+left', 'left', 'left+top'
    ]
  }

  // overrides parent behavior
  cast(position, ref) {}
  run(position, startRef, endRef) {}
}

But sadly I get the error (while testing) with Karma, jasmine and babel

TypeError: Super expression must either be null or a function, not undefined at src/core/chessmen/King.js:57

And there's no line 57 for the moment in King.js !

2条回答
Explosion°爆炸
2楼-- · 2020-05-03 10:20

If you want to have a factory, instead of saving it directly in the base class module, move it to it's own module - chessman.factory.js. There, do whatever Chessman.factory does in a method or something. This way the chessman.js module wouldn't have to know about modules that need itself,

查看更多
做个烂人
3楼-- · 2020-05-03 10:39

You have a circular dependency error. Given what you've shown us, consider the following steps:

  1. Chessman.js starts loading
  2. It pauses execution so its dependencies can load.
  3. King.js starts loading since it is a dependency.
  4. King.js throws because class King extends Chessman runs, but Chessman has not been set yet, because it paused on step #2

You'd be much better off moving your factory function to its own file, to avoid cyclical dependencies. The only safe circular dependencies in JS are ones that are not needed when the module itself is initialized. Since class extends X runs at module initialization time, it is not safe for cycles.

If this was literally your only class, you could write your app such that King.js was imported before Chessman.js, but given your usage of a factory, and your naming scheme, I assume there are other chess pieces. Since every single chess piece class will trigger this issue, there is no way to import them in the correct order. Avoiding the issue by moving the factory function out of Chessman.js is the only solution to this.

查看更多
登录 后发表回答