相信很多使用 nodejs
有朋友都會遇到了循環依賴的問題,它的原理是什么?我們怎樣在日常開發中規避掉這樣的問題?
場景重現
one.js
console.log('one init');
const two = require('./two');
var exp = module.exports = {};
console.log('one exports');
function start() {
console.log('one start');
two.start();
}
function load() {
console.log('one load');
}
exp.start = start;
exp.load = load;
two.js
console.log('two init');
const one = require('./one');
var exp = module.exports = {};
function start() {
console.log('two start');
one.load();
}
exp.start = start;
main.js
const one = require('./one')
one.start();
輸出結果
$ node main.js
one init
two init
one {}
one exports
one start
two start
E:\source\nodejs\test\loop_require\two.js:8
one.load();
^
TypeError: one.load is not a function
at Object.start (E:\source\nodejs\test\loop_require\two.js:8:9)
at Object.start (E:\source\nodejs\test\loop_require\one.js:7:9)
at Object.<anonymous> (E:\source\nodejs\test\loop_require\main.js:3:5)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:394:7)
上面的場景其實有一個循環依賴和 module.exports
的問題,首先我們肯定下造成上面的遠行異常本身不是循環依賴造成的,而是我們代碼中對 exports
使用異常造成的
module.exports
是什么?
相信細心的朋友應該知道,如果你直接 require
一個空的模塊的話,它是一個空對象,上面的場景中 two.js
引用 one.js
此時的對象為 {}
而 one.js
中對 exports
對象進行了重新指向,此時 two.js
中引用到的對象和 one.js
后續重新生成的 exports
對象已經不是一個對象了,所以在 two.js
中使用 one.start()
中的方法時提示 TypeError: one.load is not a function
如何解決
1. 把模塊的方法直接綁定到 module.exports
對象上(如果出現重復依賴時尤其要這樣做)
module.exports.start = function() {
// do something
}
exports.run = function() {
// do something
}
2. 在方法使用時再引用(不建議這樣使用)
上面場景中的 two.js 可以有如下寫法:
console.log('two init');
const one = require('./one');
var exp = module.exports = {};
function start() {
console.log('two start');
require('./one').load();
}
exp.start = start;
nodejs
本身對循環依賴的處理是很合理的,出現問題也都是我們邏輯處理上的問題,希望上面的分析和解決方案可以幫助到還被困擾中的你。