我正在努力从动态导入的类中实例化对象。基本上我有一些看起来像这样的插件:
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;
// ...
});
}));
}
加载它们时是不是有更好的方法来实例化所有这些类?
答案 0 :(得分:1)
import()
承诺没有链接,这是一个类似于this case的错误,可能会导致错误处理和竞争条件出现问题。
map
与this 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();
}));
...
}