Я пишу приложение с использованием Angular и постоянно использую этот шаблон:
Показанный вами шаблон очень похож на хранилище состояний такие как; Redux , NgRX или NGXS .Разница в том, что вы поместили магазин, селекторы и редукторы в один класс.
Наличие всего в одном месте имеет свои преимущества, но если вам придется переписывать новый магазин каждый раз, когда вы запускаете новый сервис,тогда это объяснило бы, почему вы говорите «Это происходит так часто, что код кажется очень многословным и повторяющимся» .
В этом нет ничего плохого, и в Интернете есть много постов в блоге.которые пытаются написать клон Redux, используя как можно меньше строк кода.Я хочу сказать, что люди все время делают именно то, что вы делаете.
private readonly _widgets: BehaviorSubject<Widget[]> = new BehaviorSubject([]);
Выше store менеджера состояний.Это наблюдаемая, которая содержит текущее состояние и передает изменения в это состояние.
public get widgets() { return this._widgets.value; }
Выше приведен снимок менеджера состояний.Это позволяет вам выполнять определенные вычисления в магазине без необходимости подписки, но, как и в других государственных магазинах, использующих моментальные снимки, могут возникнуть проблемы с состоянием гонки.Вы также никогда не должны обращаться к этому напрямую из шаблона, потому что он вызовет ошибку «Выражение изменилось после того, как он был проверен».
public readonly widgets$ = this._widgets.asObservable();
Выше селектор для магазина,Хранилища часто имеют много селекторов, которые позволяют различным частям приложения прослушивать изменения хранилища по определенным темам.
public add(widget: Widget) {
const old = this._widgets.value.slice();
old.push(widget);
this._widgets.next(old);
// above can be rewritten as
this._widgets.next([...this.widgets, widget]);
}
В библиотеках state store выше нет.Вышеуказанное разделено на две части: действие и редуктор .Действие часто содержит полезную нагрузку (в вашем случае - виджет), а редуктор выполняет работу по изменению хранилища.
Когда мы используем действия и редукторы, он разделяет бизнес-логику того, какХранение должно измениться от проблем чтения текущего состояния, обновления состояния и сохранения следующего состояния.Пока твой пример очень прост.В больших приложениях, требующих подписки, изменения и выдачи изменений, они могут стать стандартным кодом, когда все, что вам нужно сделать, это переключить логический флаг.
У многих служб будет 3-5 или болеетакие группы государственных добытчиков и частных субъектов поддержки.Случается так, что код кажется очень многословным и повторяющимся.
Вы вступаете в сферу нового изобретения колеса.
На мой взгляд, у вас есть два возможных варианта.Придумайте свою собственную структуру хранилища состояний, которая будет более удобной для вас, или используйте существующее хранилище состояний из одной из библиотек, перечисленных выше.Мы не можем сказать вам, какой путь выбрать, но я работал над многими Angular-проектами и могу сказать, что нет правильного ответа.
То, что действительно делает исходный код менее многословным и повторяющимся, высоко ценится,Сама вещь , которая сделала его менее многословным, может однажды вернуться к вам как к ошибке проектирования, а повторяющийся исходный код - это боль, но однажды вы будете благодарны, что можете изменить одну строку кода безэто влияет на другие области вашего исходного кода.
a) существует ли СУХОЙ способ сделать это, и
Единственный способ высушить исходный код - этоотделить реализацию state management от бизнес-логики .Здесь мы обсуждаем, как создать хороший шаблон проектирования для государственного хранилища .
- Используете ли вы селекторы?
- Используете ли вы действия?
- Используете ли вы редукторы?
Где вы хотите, чтобы эти вещи были (в своих собственных файлах или методах службы?).Как вы хотите назвать их, и следует ли вам повторно использовать их или создавать новые для каждого крайнего случая?
Это много вопросов, которые действительно являются личным выбором.
Я могу переписать ваш пример, используя NGXS в качестве примера, но это может показаться вам dry , потому что фреймворки должны быть сложными, чтобы быть полезными. Что я могу вам сказать, так это то, что вам легче читать документацию по NGXS, когда вам нужно сделать что-то, чего вы раньше не делали, а затем попытаться придумать это самостоятельно и рискнуть ошибиться. Это не значит, что NGXS всегда прав, но, по крайней мере, вы можете жаловаться, что это не ваша вина:)
@State<Widget[]>({
name: 'widgets',
defaults: []
})
export class WidgetState {
@Action(AddWidgetAction)
public add(ctx: StateContext<Widget[]>, {payload}: AddWidgetAction) {
ctx.setState([...ctx.getState(), payload]);
}
}
@Component({...})
export class WidgetsComponent {
@Select(WidgetState)
public widgets$: Observable<Widget[]>;
public constructor(private _store: Store) {};
public clickAddWidget() {
this._store.dispatch(new AddWidgetAction(new Widget()));
}
}
б) Я неправильно использую Наблюдаемые здесь?
Абсолютно не злоупотреблять наблюдаемыми. Вы хорошо понимаете, почему служба должна быть без состояний и реактивной . Я думаю, вы только что открыли для себя ценность государственных магазинов , и теперь вы ищете способы облегчить их использование.