1

我正在尝试将模板自动连接到 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

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

4

1 回答 1

1

该代码存在控制流问题。有没有被链接的承诺,这是反模式。这会导致低效的错误处理和竞争条件。

每一个承诺都应该被锁起来。在 ES6 中不鼓励使用 offorEach有几个原因,其中之一是它需要额外的操作来处理 Promise,并且不能很好地与生成器和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应该链接它并避免承诺构造反模式:

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()回退到requireNode.js 中。

于 2018-05-15T20:18:09.987 回答