如何动态绑定动态导入的类型 [英] How to dynamically bind a dynamically imported type

查看:78
本文介绍了如何动态绑定动态导入的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将模板自动地连接到inversifyjs容器,但是无论如何,它都无法正常工作.请帮忙吗?

I am trying to have templates automagically wired to an inversifyjs container but whatever I try it's not working. Please help?

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

and files ./component.html.tpl

@injectable() export default class HtmlTemplate implements ITemplate { ... }

和./component.ts.tpl

and ./component.ts.tpl

@injectable() export default class ComponentTemplate implements ITemplate { ... }

完全按预期方式登录到控制台:

Which logs completely as expected to the console:

[Function: HtmlTemplate] { file: './component.html.tpl', obj: 'HtmlTemplate' }
[Function: ComponentTemplate] { file: './component.tpl.ts', obj: 'ComponentTemplate' }

但是我真的希望foreach语句中的代码:

But I really expected the code in the foreach statement:

this.container.bind<ITemplate>(template.obj).to(mod.default);

等同于此:

this.container.bind<HtmlTemplate>('HtmlTemplate').to(HtmlTemplate);
this.container.bind<ComponentTemplate>('ComponentTemplate').to(ComponentTemplate);

但是当我尝试在另一个循环中解决它时:

but when I try to resolve it in an other loop:

this.templates.forEach(template => {
    const tpl = this.container.get<ITemplate>(template.obj);
...

它会引发错误:

Error: No matching bindings found for serviceIdentifier HtmlTemplate

有人知道如何解决这个问题吗?

Anyone know how to solve this?

推荐答案

代码在控制流方面存在问题.有没有被链接的承诺,这是反模式.这导致错误处理和竞态条件的效率低下.

The code has problems with control flow. There are promises that aren't chained, which is antipattern. This results in inefficient error handling and race conditions.

每一个应许都应该被束缚起来.在ES6中不鼓励使用forEach,其原因有几个,其中之一是它要求额外的操作才能与promises一起使用,并且不适用于生成器和async函数.该代码可以使用大多数async函数,并可以进行重构以使控制流更加干净和有效:

Each and every promise should be chained. The use of forEach is discouraged in ES6 for several reasons, one of them is that it requires additional actions to work with promises and doesn't work well with generators and async functions. The code can take most of async functions and be refactored to make control flow clean and efficient:

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构造反模式:

The code that uses bind should chain it and avoid promise construction antipatterns:

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() Promise可以用同步的require语句替换,import()可以以任何方式退回到Node.js中的require.

A more efficient way is to discard asynchronous initialization routine, because the only thing that requires it is dynamic import(). import() promises can be replaced with synchronous require statements, import() falls back to require in Node.js any way.

这篇关于如何动态绑定动态导入的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆