上一节我们学习了关于didi
依赖注入框架的关于组件和加载器作用域相关的使用,今天我们来了解一些初始化的一些使用。
我们还是用一些例子来说明问题
const { Injector } = require('didi');
const { expect } = require('chai');
const injector = new Injector([
{
__init__: [ 'foo' ],
'foo': [ 'factory', function(bar) {
bar.initialized = true;
return bar;
} ],
'bar': [ 'value', {} ]
}
]);
const bar1 = injector.get('bar');
console.log('bar1:',bar1 );
// when
injector.init();
const bar = injector.get('bar');
// then
expect(bar.initialized).to.be.true;
console.log('init component');
输出如下:

从以上代码可以看出,从加载器中没有获取过foo
组件,因此foo
不会初始化,但是可以将其配置在__init__
中,因此这个组件一开始就直接初始化,然后会将依赖的bar组件设置一个bar.initialized = true
,因此我们知道这个值会等于true。
从以上可以得出,在构造Injector
的时候,组件是不会初始化的,只有配置在__init__
中并且调用init
方法的时候,获取调用get
,invoke
的时候才会初始化相应的组件。
我们继续看下面的一个例子,就是私有组件的初始化情况:
const { Injector } = require('didi');
const { expect } = require('chai');
const privateBar = {};
const injector = new Injector([
{
__exports__: [ 'publicFoo' ],
__init__: [ function(privateBar) {
privateBar.initialized = true;
} ],
'publicFoo': [
'factory',
function(privateBar) {
return {
privateBar
};
}
],
'privateBar': [ 'value', {} ]
}
]);
// when
injector.init();
const publicFoo = injector.get('publicFoo');
expect(publicFoo.privateBar.initialized).to.be.true;
console.log('private module');
输出如下

从以上的代码不难看出,在初始化一个模块的组件的时候,是可以修改私有组件的一些属性的,虽然不能理解为啥要这么设计,不过只要这个init的组件不被暴露出去,应该还是没有多大风险的。从这里不难看出,在初始化的时候,修改了私有组件privateBar的属性,这里有个好处就是,我可以在初始化的时候配置不同的私有实现,起到了扩展代码的作用。
下面我们看看另一个问题,那就是依赖的执行顺序是怎么样的?
const { Injector } = require('didi');
const { expect } = require('chai');
const loaded = [];
// given
const injector = new Injector([
{
__depends__: [
{
__depends__: [
{
__init__: [ function() { loaded.push('L2_A'); } ]
},
{
__init__: [ function() { loaded.push('L2_B'); } ]
}
],
__init__: [ function() { loaded.push('L1'); } ]
}
],
__init__: [ function() { loaded.push('ROOT'); } ]
}
]);
// when
injector.init();
// then
expect(loaded).to.eql([
'L2_A',
'L2_B',
'L1',
'ROOT'
]);
console.log('should load in reverse order');
输出如下:

从以上输出可以看出,在初始化组件(模块)的时候,执行的顺序是从内待外的,其实这个也不难理解,只有依赖的组件(模块)构造好了以后才能构造外层的组件。因此我们可以简单的理解为是反序的。
我们再来看看如果多次依赖相同的模块,会发生什么情况?
const { Injector } = require('didi');
const { expect } = require('chai');
const loaded = [];
const duplicateModule = /** @type ModuleDeclaration */ ({
__init__: [ function() { loaded.push('DUP'); } ]
});
// given
const injector = new Injector([
{
__depends__: [
{
__depends__: [
duplicateModule,
duplicateModule
],
__init__: [ function() { loaded.push('L1'); } ]
},
duplicateModule
],
__init__: [ function() { loaded.push('ROOT'); } ]
}
]);
// when
injector.init();
// then
expect(loaded).to.eql([
'DUP',
'L1',
'ROOT'
]);
console.log('should de-duplicate');
输出如下

从以上的输出可以看出,这些依赖会重用相同的依赖模块,而不会重复构建模块。