在promisified import

时间:2018-05-16 19:50:33

标签: node.js typescript asynchronous import

我正在努力从动态导入的类中实例化对象。基本上我有一些看起来像这样的插件:

export interface IPlugin {
    compile(logEvent: LogEventInfo): string;
}

export class DatePlugin implements IPlugin {
    public compile(logEvent: LogEventInfo): string {
        const date: Date = new Date();
        return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
    }
}

在另一个文件中,我想动态抓取文件夹,加载所有源文件并实例化它们。我看到import(...).then()可以返回一个加载的对象但是在我的情况下它返回了类,我的对象创建看起来非常难看:

public async loadPlugins(): Promise<void> {
    // ...
    await Promise.all(pluginFiles.map(async (pluginFile: string): Promise<void> => {
        const pluginFilePath: string = path.join(pluginsFolder, pluginFile);
        import(pluginFilePath).then((plugin: any): void => {
            const obj: IPlugin = (new plugin[Object.keys(plugin)[0]]() as IPlugin;
            // ...
        });
    }));
}

加载它们时是不是有更好的方法来实例化所有这些类?

1 个答案:

答案 0 :(得分:1)

import()承诺没有链接,这是一个类似于this case的错误,可能会导致错误处理和竞争条件出现问题。

mapthis case有共同的潜在问题。它仅用于提供等待它们的承诺,而不是实际值。由于async函数调用的目的是获取类实例,因此将pluginFile输入映射到obj输出值(如果它应该存储在那时)或compile结果是合理的如果不是:

public async loadPlugins(): Promise<...> {
  const plugins = await Promise.all(pluginFiles.map(async (pluginFile: string): Promise<IPlugin> => {
    const pluginFilePath: string = path.join(pluginsFolder, pluginFile);
    const pluginExports = await import(pluginFilePath);

    // preferably pluginExports.default export to not rely on keys order
    const Plugin: { new(): IPlugin } = Object.values(pluginExports)[0];
    return new Plugin();
  }));
  ...
}

import提供的唯一真正好处是它可以面向未来,它可以在Node.js中与第三方无缝地一起使用本地 ES模块(.mjs)文件。由于TypeScript以任何方式使用并且使用require进行ES模块导入,因此放弃异步例程并使用require同步而不是import进行动态导入可能是合理的:

public loadPlugins(): <...> {
  const plugins = pluginFiles.map((pluginFile: string): IPlugin => {
    const pluginFilePath: string = path.join(pluginsFolder, pluginFile);
    const pluginExports = require(pluginFilePath);

     // preferably pluginExports.default export to not rely on keys order
    const Plugin: { new(): IPlugin } = Object.values(pluginExports)[0];
    return new Plugin();
  }));
  ...
}