本文重點是講解如何解決循環依賴這個問題
。關心這個問題是如何產生的,能夠自行谷歌。node
// a.js const {sayB} = require('./b.js') sayB() function sayA () { console.log('say A') } module.exports = { sayA }
// b.js const {sayA} = require('./a.js') sayA() function sayB () { console.log('say B') } module.exports = { sayB }
執行下面的代碼git
➜ test git:(master) ✗ node a.js /Users/dd/wj-gitlab/tools/test/b.js:3 sayA() ^ TypeError: sayA is not a function at Object.<anonymous> (/Users/dd/wj-gitlab/tools/test/b.js:3:1) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Module.require (module.js:579:17) at require (internal/module.js:11:18) at Object.<anonymous> (/Users/dd/wj-gitlab/tools/test/a.js:1:78) at Module._compile (module.js:635:30)
sayA is not a function
那麼sayA是個什麼呢,實際上它是 undefined
github
遇到這種問題時,你最好能意識到多是循環依賴的問題
,不然找問題可能事倍功半。工具
上文的示例代碼很簡單,2個文件,很容易找出循環依賴。若是有十幾個文件,手工去找循環依賴的文件,也是很是麻煩的。
gitlab
下面推薦一個工具 madge, 它能夠可視化的查看文件之間的依賴關係。ui
注意下圖1,以cli.js爲起點,全部的箭頭都是向右展開的,這說明沒有循環依賴。若是有箭頭出現向左逆流,那麼就多是循環依賴的點。
spa
圖2中,出現向左的箭頭,說明出現了循環依賴,說明要此處斷開循環。code
【圖1】
【圖2】blog
將module.exports放到文件頭部,先將自身模塊導出,而後再導入其餘模塊。圖片
來自:http://maples7.com/2016/08/17...
// a.js module.exports = { sayA } const {sayB} = require('./b.js') sayB() function sayA () { console.log('say A') }
// b.js module.exports = { sayB } const {sayA} = require('./a.js') console.log(typeof sayA) sayA() function sayB () { console.log('say A') }
經過引入一個event的消息傳遞,讓多個個模塊能夠間接傳遞消息,多個模塊之間也能夠經過發消息相互調用。
// a.js require('./b.js') const bus = require('./bus.js') bus.on('sayA', sayA) setTimeout(() => { bus.emit('sayB') }, 0) function sayA () { console.log('say A') } module.exports = { sayA }
// b.js const bus = require('./bus.js') bus.on('sayB', sayB) setTimeout(() => { bus.emit('sayA') }, 0) function sayB () { console.log('say B') } module.exports = { sayB }
// bus.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} module.exports = new MyEmitter()
出現循環依賴,每每是代碼的結構出現了問題。應當主動去避免循環依賴這種問題,可是遇到這種問題,沒法避免時,也要意識到是循環依賴致使的問題,並找方案解決。
最後給出一個有意思的問題,下面的代碼運行node a.js
會輸出什麼?爲何會這樣?
// a.js var moduleB = require('./b.js') setInterval(() => { console.log('setInterval A') }, 500) setTimeout(() => { console.log('setTimeout moduleA') moduleB.sayB() }, 2000) function sayA () { console.log('say A') } module.exports = { sayA }
// b.js var moduleA = require('./a.js') setInterval(() => { console.log('setInterval B') }, 500) setTimeout(() => { console.log('setTimeout moduleB') moduleA.sayA() }, 2000) function sayB () { console.log('say B') } module.exports = { sayB }