Импорт зависимости ES6 внутри конструктора класса

#javascript #node.js #ecmascript-6 #es6-modules

Вопрос:

У меня есть класс JS/ES6 с конструктором, который должен динамически загружать зависимость на основе переданных ему настроек.

Он отлично работает с синтаксисом CommonJS:

 class Example {
    handler = null;

    constructor(dependency) {
        try {
            this.handler = new (require(dependency))();
        } catch {
            throw new Error(`${dependency} not installed`);
        }
    }
    /* ... */
}
 

Однако мне не удалось заставить его работать должным образом в формате модуля ES6. Вот и все, до чего я смог добраться:

 class Example {
    handler = null;

    constructor(dependency) {
        try {
            this.handler = new (await import(dependency)).default();
        } catch {
            throw new Error(`${dependency} not installed`);
        }
    }
    /* ... */
}
 

Это не работает , потому что вы не можете использовать await без async , и конструктор класса не может быть async .

Без await этого дальнейший код , как правило, завершается ошибкой, так как нет гарантии, что зависимость была загружена вовремя.

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

Я бы предпочел не иметь отдельного метода инициализации/сборки, о котором потребителю нужно беспокоиться. В идеале вы должны иметь возможность просто выполнять const ex = new Example('some-dependency') , а затем иметь мгновенный доступ к методам класса в ex , без какой-либо необходимости в дополнительных шаблонах на стороне потребителя.

Конструктор, конечно, мог бы вызвать метод статической сборки, но это, похоже, просто перемещает асинхронную проблему в другое место.

Существует ли установленный шаблон или взлом kludgey для достижения этой цели в модулях ES6?

Комментарии:

1. если вы не можете использовать асинхронность, используйте Promise

2. Если вы динамически импортируете, то вы выбираете асинхронное поведение. Можете ли вы экспортировать async function createExample(dependency) { const dep = await import(dependency); return new Example(dep); } вместо этого? В противном случае ваш единственный вариант состоял бы в том, чтобы все, что используется this.handler , было асинхронным, и чтобы этот код был тем, что выбрасывается в случае сбоя импорта.