Javascript. Какой использовать паттерн инициализации класса с асинхронным запросом внутри?
Цель - получить своеобразную абстрактную модель, которая сама подгрузит необходимые данные ajax-запросом. Вызывать ajax-запрос в конструкторе - не самая хорошая идея. То есть, мы конечно можем проставить все необходимые поля из коллбэка запроса, но если у класса будут наследники, которые используют результат инициализации родителя, коллбэк запроса отработает позже инициализации наследника.
Иначе говоря, мне бы хотелось заблокировать инициализацию до момента пока запрос не будет завершен. Пока на ум приходит 3 варианта:
1. Использовать синхронный запрос (априори плохая идея)
2. В конструкторе родителя отправить запрос, из коллбэка вызвать некий метод, который обработает результат и вернет Promise, затем в потомке, основываясь на результатах промиза, продолжать инициализацию.
3. Использовать фабричный метод, который сам отправит запрос, затем уже коллбэк запроса вернет инстанс класса.
Подскажите, может я чего-то упускаю и можно это сделать проще и красивше?
Идея изначально была такая, что есть некий абстрактный клас модели, его задача - загрузить данные и предоставить их для анализа конкретным потомкам. Условно говоря:
class Model {
constructor(params){ loadData(); } //загружаем данные асинхронно, сохраням результат загрузки в this.
}
class User extends Model {
constructor(id) {
super({'id': id}) //генерируем некоторые специфичные параметры для запроса и отправляем родителю
//анализируем ответ
}
}
Ну понятно, что для того, чтобы такой код работал, нам надо тем или иным образом дождаться пока запрос будет завершен. Конкретных моделей несколько. И все они забирают данные с сервера.
Как все это представить в качестве композиции объектов слабо укладывается в голове. Впрочем, фабрика в данной ситуации тоже не то чтобы спасение: поручаем всю грязную работу по загрузке данных фабрике, в коллбэке загрзузчика инициализируем нужный класс, инстанс уже анализирует полученные данные, но тогда коллбэк должен знать, куда результат (инстанс) положить.
Объекту с данными незачем знать, как эти данные хранятся. Поэтому да, фабрика. На худой конец фабричная функция может быть статическим методом этого класса, но не более.
С фабрикой есть сложность. Надо как-то выяснить имя класса из которого фабричный метод был вызван. Либо создавать по фабрике на каждый класс модели, но это убивает всю идею наследования в данной ситуации.
Если речь о фабричном статическом методе класса, то this.name даст имя класса (если он не анонимный, конечно).
Но вообще лучше сделать совсем отдельно. Повторюсь, value object не должен знать, откуда он берется.