如何动态绑定动态导入的类型
How to dynamically bind a dynamically imported type
我正在尝试将模板自动连接到 inversifyjs 容器,但无论我尝试什么,它都不起作用。请帮忙?
private templates = [
{file: './component.html.tpl', obj: 'HtmlTemplate'},
{file: './component.tpl.ts', obj: 'ComponentTemplate'}
];
private container = new Container();
bind(){
// original and working code
// this.container.bind<ITemplate>('HtmlTemplate').to(HtmlTemplate);
// this.container.bind<ITemplate>('ComponentTemplate').to(ComponentTemplate);
this.templates.forEach(template => {
import(template.file).then(mod => {
console.log(mod.default, template);
// is this correct (seems to work) =>
this.container.bind<ITemplate>(template.obj).to(mod.default);
console.log('bound =>', mod.default);
});
});
}
和文件./component.html.tpl
@injectable() export default class HtmlTemplate implements ITemplate { ... }
和./component.ts.tpl
@injectable() export default class ComponentTemplate implements ITemplate { ... }
它完全按照预期记录到控制台:
[Function: HtmlTemplate] { file: './component.html.tpl', obj: 'HtmlTemplate' }
[Function: ComponentTemplate] { file: './component.tpl.ts', obj: 'ComponentTemplate' }
但我真的很期待foreach语句中的代码:
this.container.bind<ITemplate>(template.obj).to(mod.default);
相当于:
this.container.bind<HtmlTemplate>('HtmlTemplate').to(HtmlTemplate);
this.container.bind<ComponentTemplate>('ComponentTemplate').to(ComponentTemplate);
但是当我尝试在另一个循环中解决它时:
this.templates.forEach(template => {
const tpl = this.container.get<ITemplate>(template.obj);
...
它抛出一个错误:
Error: No matching bindings found for serviceIdentifier HtmlTemplate
有人知道如何解决这个问题吗?
代码在控制流方面存在问题。有些承诺没有链接,这是反模式。这会导致低效的错误处理和竞争条件。
每一个承诺都应该被链接起来。在 ES6 中不鼓励使用 forEach
有几个原因,其中之一是它需要额外的操作来处理承诺,并且不能很好地与生成器和 async
函数一起使用。该代码可以采用大部分 async
函数并进行重构以使控制流简洁高效:
async bind(){
for (const template of this.templates)
const mod = await import(template.file);
this.container.bind<ITemplate>(template.obj).to(mod.default);
}
}
使用 bind
的代码应该链接它并避免 promise 构造反模式:
async bind() {
// binding for when the widget is needed;
for (const component of this.components)
component.widget = this.container.get<Widget>(component.name);
if(component.widget) {
await component.widget.configure();
await component.widget.bind();
} else {
console.error(`widget ${component.name} not resolved`);
}
});
return this;
}
一种更有效的方法是放弃异步初始化例程,因为唯一需要它的是动态的 import()
。 import()
promises 可以替换为同步 require
语句,import()
回退到 Node.js 中的 require
任何方式。
我正在尝试将模板自动连接到 inversifyjs 容器,但无论我尝试什么,它都不起作用。请帮忙?
private templates = [
{file: './component.html.tpl', obj: 'HtmlTemplate'},
{file: './component.tpl.ts', obj: 'ComponentTemplate'}
];
private container = new Container();
bind(){
// original and working code
// this.container.bind<ITemplate>('HtmlTemplate').to(HtmlTemplate);
// this.container.bind<ITemplate>('ComponentTemplate').to(ComponentTemplate);
this.templates.forEach(template => {
import(template.file).then(mod => {
console.log(mod.default, template);
// is this correct (seems to work) =>
this.container.bind<ITemplate>(template.obj).to(mod.default);
console.log('bound =>', mod.default);
});
});
}
和文件./component.html.tpl
@injectable() export default class HtmlTemplate implements ITemplate { ... }
和./component.ts.tpl
@injectable() export default class ComponentTemplate implements ITemplate { ... }
它完全按照预期记录到控制台:
[Function: HtmlTemplate] { file: './component.html.tpl', obj: 'HtmlTemplate' }
[Function: ComponentTemplate] { file: './component.tpl.ts', obj: 'ComponentTemplate' }
但我真的很期待foreach语句中的代码:
this.container.bind<ITemplate>(template.obj).to(mod.default);
相当于:
this.container.bind<HtmlTemplate>('HtmlTemplate').to(HtmlTemplate);
this.container.bind<ComponentTemplate>('ComponentTemplate').to(ComponentTemplate);
但是当我尝试在另一个循环中解决它时:
this.templates.forEach(template => {
const tpl = this.container.get<ITemplate>(template.obj);
...
它抛出一个错误:
Error: No matching bindings found for serviceIdentifier HtmlTemplate
有人知道如何解决这个问题吗?
代码在控制流方面存在问题。有些承诺没有链接,这是反模式。这会导致低效的错误处理和竞争条件。
每一个承诺都应该被链接起来。在 ES6 中不鼓励使用 forEach
有几个原因,其中之一是它需要额外的操作来处理承诺,并且不能很好地与生成器和 async
函数一起使用。该代码可以采用大部分 async
函数并进行重构以使控制流简洁高效:
async bind(){
for (const template of this.templates)
const mod = await import(template.file);
this.container.bind<ITemplate>(template.obj).to(mod.default);
}
}
使用 bind
的代码应该链接它并避免 promise 构造反模式:
async bind() {
// binding for when the widget is needed;
for (const component of this.components)
component.widget = this.container.get<Widget>(component.name);
if(component.widget) {
await component.widget.configure();
await component.widget.bind();
} else {
console.error(`widget ${component.name} not resolved`);
}
});
return this;
}
一种更有效的方法是放弃异步初始化例程,因为唯一需要它的是动态的 import()
。 import()
promises 可以替换为同步 require
语句,import()
回退到 Node.js 中的 require
任何方式。