CommonJS和ES6 Module分别如何处理循环依赖的问题?

3,529 阅读2分钟

CommonJS和ES6 Module分别如何处理循环依赖的问题?

前篇(CommonJS和ES6 Module的区别):juejin.cn/post/695936…

前言:一般来说工程中应该尽量避免循环依赖的产生,因为从软件设计的角度来说,单向的依赖关系更加清晰,而循环依赖则会带来一定的复杂度。

  • 但工程的复杂度上升到足够规模时,就容易出现隐藏的循环依赖关系。简单来说,A和B两个模块之间是否存在直接的循环依赖关系是很容易被发现的。但实际情况往往是A依赖于B,B依赖于C,C依赖于D,最后绕了一大圈,D又依赖于A。当中间模块太多时就很难发现A和B之间存在着隐式的循环依赖。

实际代码举例

目录结构:

├── main.js
├── bar.js
├── aaa.js

commonjs中 循环依赖的情况(注释内有解析

// main.js
const bar = require('./bar.js')
console.log('当前是main.js内:', bar) // {}
module.exports = '在main.js内'

// bar.js
const main = require('./main.js')
console.log('当前是bar.js内:', main)
module.exports = 'bar.js内'

// 执行 node ./main.js  , 输出:
当前是bar.js内: {}  // 解析:执行到bar.js内时,main.js还没有执行完,就没有东西导出,会默认导出空对象
当前是main.js内: bar.js

es6 module中 循环依赖的情况(注释内有解析

// main.js
import bar from './bar.js'
console.log('当前是main.js内:', bar)
export default '在main.js内'

// bar.js
import main from './main.js'
console.log('当前是bar.js内:', main)
export default 'bar.js内'

// 执行 webpack-dev-server xx 启服务去执行  入口是main.js  , 输出:
当前是bar.js内: undefined  // 解析:编译到bar.js内时,main.js还没有编译完,就没有东西编译映射到main这个变量上去,就是undefined
当前是main.js内: bar.js

解决方法

用es6 module:因为他的值的动态映射的,可以在模块都解析完后,得到变更后的状态

具体方法举例:

方法一: 异步,比如setTimeout

// main.js
import bar from './bar.js'
console.log('当前是main.js内:', bar)
export default '在main.js内'

// bar.js
import main from './main.js'
console.log('当前是bar.js内:', main)
setTimeout(() => {
  console.log('当前是bar.js内:', main) // 这里能输出,因为main.js已经解析完了,(export default '在main.js内')这一行解析完了
})
export default 'bar.js内'

// 执行 webpack-dev-server xx 启服务去执行  入口是main.js  , 输出:
当前是bar.js内: undefined
当前是main.js内: bar.js内
当前是bar.js内: 在main.js

方法二:导出一个函数

// main.js
import a from './a.js'
a()

// a.js
import b from './b.js'
export default function () {
  console.log('当前是a.js内:', b())
}

// b.js 导出一个函数
import a from './a.js'
export default function () {
  console.log('当前是b.js内:', a())
}

码字不易,点赞鼓励!!