Легенда
action-chain epic
= Epic, который возвращает действие «успех» или «сбой» в зависимости от вызова службы. service
= Служба HTTP, от HttpModule
, Angular2
Цель
Мне нужно отправить данные на сервер. У меня есть действия CREATE
, CREATE_SUCCESS
и CREATE_FAIL
. Моя идея состоит в том, чтобы отправить CREATE
при отправке. Затем у меня есть action-chain epic
, который запускает service
вызов моего сервера и запускает CREATE_SUCCESS
или CREATE_FAIL
в зависимости от ответа.
Эта проблема
Мой action-chain epic
запускает повторяющиеся действия - в обоих случаях он запускает два действия, например: в случае успеха для каждого CREATE
он отправляет два CREATE_SUCCESS
действия.
Код
private createAnimalActionChain() {
return action$ => {
return action$
.ofType(AnimalActions.CREATE)
.switchMap(action => {
return this.service
.create(action.payload)
.map(httpResponse => {
let response = httpResponse.json()
if (response.success) {
return this.actions.createSuccess()
}
return this.actions.createFail(response.errors)
})
})
}
}
Это то, что я сочинил, и по большей части это работает. Если есть лучший подход, я все уши. До недавнего времени отправка нескольких действий не была реальной проблемой, но мне никогда не казалось, что это нормально, поэтому я хотел бы исправить это.
РЕДАКТИРОВАТЬ: я только что обнаружил, что иногда мое приложение отправляет повторяющиеся действия до выполнения любого Epic. Я сейчас пытаюсь понять, почему.
РЕДАКТИРОВАТЬ 2: не обращайте внимания на ИЗМЕНИТЬ. Это был единичный случай, когда событие отправки поднималось до самого верха, и поскольку я назвал свое поле @Output()
'submit', это вызвало отправку двойного действия. Теперь это исправлено и не имеет отношения к описанной выше проблеме Epic. Это все еще сохраняется.
ИЗМЕНИТЬ 3. С помощью @jayphelps мне удалось отследить проблему. Оказывается, мои действия, вызванные из эпической цепочки, сработали дважды. Я не уверен, почему это происходит. Вот мой старый код:
static CREATE = 'CREATE'
static CREATE_SUCCESS = 'CREATE_SUCCESS'
static CREATE_FAIL = 'CREATE_FAIL'
@dispatch()
create = (animal: IAnimal) => ({
type: AnimalActions.CREATE,
payload: animal
})
@dispatch()
createSuccess = () => ({
type: AnimalActions.CREATE_SUCCESS
})
@dispatch()
createFail = (errors: object) => ({
type: AnimalActions.CREATE_FAIL,
payload: errors
})
Этот код отправляет CREATE
один раз, CREATE_SUCCESS
дважды и CREATE_FAIL
дважды. Я удалил два последних @dispatch()
декоратора:
static CREATE = 'CREATE'
static CREATE_SUCCESS = 'CREATE_SUCCESS'
static CREATE_FAIL = 'CREATE_FAIL'
@dispatch()
create = (animal: IAnimal) => ({
type: AnimalActions.CREATE,
payload: animal
})
createSuccess = () => ({
type: AnimalActions.CREATE_SUCCESS
})
createFail = (errors: object) => ({
type: AnimalActions.CREATE_FAIL,
payload: errors
})
Кажется, что этот код работает правильно и запускает только одно действие. Я очень не понимаю, почему это так работает. Согласно документам API, это свойство украшает единственная функция-создатель действия и отправляет ее возвращаемое значение, объект действия. это очень странно, потому что я называю CREATE
и CREATE_SUCCESS
одинаково. Как работает этот декоратор?
РЕДАКТИРОВАТЬ 4: я сузил поведение до следующего: если я вызываю действие из моего Epic, и это действие украшено @dispatch
, оно запускается дважды. Я подозреваю, что Epic, будучи промежуточным программным обеспечением, отправляет полученное действие внутри себя. Проблема возникает, если мне нужно вручную отправить действие из моего компонента контейнера.
Решение
С помощью jayphelps. Спасибо за ваш ответ. Однако мне нравится @dispatch
украшение для использования внутри моих компонентов. Пресональное решение, которое я нашел, - это структурирование моей цепочки действий таким образом, чтобы starter-actions
(те, которые отправляются изнутри компонента) не отправлялись через Epic. Тогда просто украсьте эти starter-actions
цветом @dispatch
, и все заработает.