這在個案的基礎上肯定是可以接受的。靜態或原型someModule
屬性會更有效率,但另一方面,這將需要在測試中嘲笑後恢復它。
定期這種模式可能會變得麻煩,在這種情況下,DI容器可能會更方便。在Node領域有很多,例如injection-js
that was extracted from Angular DI。
在其最簡單的形式可以是不下隨機令牌創建自身實例,但現有的值(模塊出口)存儲一個純粹的單容器:
class Container extends Map {
get(key) {
if (this.has(key)) {
return super.get(key);
} else {
throw new Error('Unknown dependency token ' + String(key));
}
}
set(key, val) {
if (key == null) {
throw new Error('Nully dependency token ' + String(key));
} else if (arguments.length == 1) {
super.set(key, key);
} else {
super.set(key, val);
}
}
}
const container = new Container;
的依賴可以登記與檢索直接從容器:
const foo = Symbol('foo');
container.set(foo, require('foo'));
container.set('bar', require('bar'));
container.set(require('baz'));
...
const { foo } = require('./common-deps');
class Qux {
constructor() {
this.foo = container.get(foo);
...
}
}
此外,噴射器可以擁抱容器:
class DI {
constructor(container) {
this.container = container;
}
new(Fn) {
if (!Array.isArray(Fn.annotation)) {
throw new Error(Fn + ' is not annotated');
}
return new Fn(...Fn.annotation.map(key => this.container.get(key)));
}
call(fn) {
if (!Array.isArray(fn.annotation)) {
throw new Error(fn + ' is not annotated');
}
return fn(...fn.annotation.map(key => this.container.get(key)));
}
}
const di = new DI(container);
照顧DI的註解類和函數(上標註,見this explanation):
class Qux {
constructor(foo, bar) {
this.foo = foo;
...
}
}
Qux.annotation = [foo, 'bar', require('baz')];
quuxFactory.annotation = [require('baz')]
function quuxFactory(baz) { ... }
const qux = di.new(Qux);
const quux = di.call(quuxFactory);
我會接受你的答案,並給予直接投資框架一試。非常感謝詳細的信息:)一些更多的信息:我更廣泛地瞭解了可用於節點的各種DI框架並嘗試了其中的幾個。我發現https://github.com/justmoon/constitute有一個非常乾淨和輕量級的API(似乎也受到了Angular DI概念的啓發)。 – benjiman
不客氣。感謝分享,我會檢查它。作者承認它大部分複製了Aurelia DI,因此您可以查看[其手冊](http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection - 基礎/ 6)的一些概念。關於injection-js的好處是它支持並且在Angular手冊中有很好的文檔記錄,對於Angular的fullstack開發也非常簡單。 – estus