Создание объекта после обещанного импорта - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь создать экземпляр объекта из динамически импортируемых классов.В основном у меня есть несколько плагинов, которые выглядят примерно так:

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 голосов
/ 17 мая 2018

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();
  }));
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...