在承诺导入后实例化对象



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

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;
// ...
});
}));
}

加载时没有更好的方法来实例化所有这些类吗?

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

map与此案例有一个共同的潜在问题。它仅用于提供等待它们的承诺,而不是实际值。由于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();
}));
...
}

最新更新