Должна ли служба Angular иметь статус?
Недавно у некоторых коллег и я обсуждали, нужно ли иметь услуги AngularJS или нет. Мы придумали некоторые аргументы за и против, и я хотел получить дополнительные мысли и отзывы по этому вопросу. В моем поиске я нашел этот, но, похоже, не существует какой-либо четкой передовой практики. В мире клиентской стороны служба никогда не должна оставаться в состоянии, но я начинаю думать, что она может быть приемлемой на стороне клиента, потому что у нее другая проблема.
Причины для состояния обслуживания:
- Служба не будет доступна для нескольких потоков. Каждый браузер будет иметь свой собственный экземпляр службы.
- Позволяет службе сохранять состояние только в этом случае, а не хранить его в корневой системе. инкапсулирует
Причины, по которым службы не сохраняются:
- Сервисы больше не являются идемпотентными. Функции вызова могут изменять состояние и, следовательно, могут иметь разные результаты при вызове на основе состояния службы.
- Я бы подумал, что в целом это было бы легче протестировать.
Один из способов, который мог бы адресовать номер 2 в разделе "Состояние обслуживания", - это иметь объект appState, установленный на rootScope, который содержит текущее состояние приложения. Тогда все государство будет собрано в одном месте, а затем вы просто вытащите то, что вам нужно, в вашем сервисе. Я нашел это и задавался вопросом
Ответы
Ответ 1
В AngularJS услуги передаются через функцию factory. И в основном это объекты, которые могут содержать некоторое состояние (например, для кэширования или хранения данных, необходимых для выполнения их действий).
Одним из хороших решений, которые могут принимать оба недостатка, имеющие/не имеющие состояния, является то, что служба (которая фактически может функционировать) возвращает объект, содержащий состояние.
Посмотрите на службу $http
: вы можете получить экземпляр этой службы, вызывающий
var x = $http({url:'...'});
А затем вызовите
var result = x.get() //actually `$http.get` is shortcut of this operation
То же самое с ngResource
: используя службу, вы получаете объект с некоторым состоянием, которое может выполнять требуемые действия.
В принципе, я думаю, что это лучший вариант: с одной точки вы избегаете "побочных эффектов" путем перемещения состояния, которое может быть изменено действием на отдельный объект, а не храниться в самом сервисе, но может иметь определенное состояние в этом объекте иметь возможность хранить пользовательскую информацию (например, информацию об аутентификации и т.д.).
Ответ 2
Вероятно, это зависит от того, что вы подразумеваете под "состоянием", но во многих случаях я думаю, что ответ будет да: службы должны иметь состояние.
Например, если у вас есть служба, которая отвечает за связь с API, эта служба может содержать состояние аутентификации.
Кстати, я не уверен, сколько идемпотенции имеет значение для сервисов AngularJS - они являются одноточиями и поэтому имеют определенное состояние. Вы могли (и в некоторых случаях должны) создавать идемпотентные методы в службе, но это отдельная проблема.
Ответ 3
ИМО да, службы МОГУТ иметь состояния. Я говорю, что "может", поскольку услугу можно рассматривать как нечто похожее на классическую не клиентскую службу - провайдера, но это также может означать нечто совершенно иное, в angularJS. Как элемент rootScope-y one-instance в приложении, он может использоваться исключительно для управления состоянием, например. В моем случае это позволяет мне обеспечить, чтобы структура штата была одинаковой во многих приложениях, и хотя их индивидуальная структура состояния определена для каждого в процессе начальной загрузки, такие вещи, как состояние сеанса, всегда остаются неизменными и обновляются, когда этот модуль изменяется.
Ответ 4
Причина, по которой службы не должны иметь состояния, заключается в том, что она приводит к условиям гонки, когда у вас есть несколько потоков, обращающихся к службе.
Общая проблема с состоянием в службе:
- поток 1 записывает в состояние
- поток 2 записывает в состояние
- поток 1 читается из состояния
- поток 2 читается из состояния
В потоке 1 теперь есть неправильное значение.
Как говорится, javascript в настоящее время однопоточен, поэтому у вас не будет проблем с доступом к потоку. Тем не менее, я был бы обеспокоен, если бы у меня была служба, в которой все асинхронные $http-вызовы записывались в одну и ту же служебную переменную. Если бы только я мог лучше спать ночью, я бы попытался написать все свои методы обслуживания, чтобы они были сквозными для фактических данных.
Вместо того, чтобы поддерживать состояние службы, вы могли бы рассмотреть возможность как можно большего количества состояний в бэкэнд. Такие вещи, как "аутентифицированные" или даже ширины и высоты, могут поддерживаться и запрашиваться. Это может открыть некоторые возможности для того, чтобы пользователи могли перейти от приложения, вернуться и найти все свои настройки, которые все еще настроены и вошли в систему. Вы можете сохранить идентификатор сеанса в файле cookie и сохранить все это на бэкэнд.
Если вы отправили маршрут наличия отдельного объекта для хранения состояния, вы могли бы исправить его из службы, если что-то в состоянии изменилось: как сделать испускать события из factory. Это имело бы хороший побочный эффект, заключающийся в том, что несколько служб могут изменять состояние унифицированного приложения, поскольку состояние не сохраняется в какой-либо одной службе (или, что еще хуже, распространено среди нескольких служб).