Проверьте данные в Angular Store перед вызовом API с помощью NGRX с использованием наблюдаемых
Я использую Angular с эффектами NGRX, и я новичок в мире наблюдаемых. Я хочу проверить, что если данные существуют в моем хранилище, то API не должен вызываться, а данные должны извлекаться из хранилища. Мне удалось найти, что я могу использовать withLatestFrom(), который может проверить последнее значение в магазине. Следующая часть сбивает меня с толку, и я не могу заставить его работать. Мой текущий код ниже:
@Effect() getSomeContent$ = this.actions$
.ofType(GET_SOME_CONTENT)
.withLatestFrom(this.store$.select('store-section'))
.map(([action, store]) => {
const content = {};
if (store.someContent.length > 0) {
return new GetCategoryContentSuccessAction({ categoryContent: categories });
}
return Observable.from(action.payload);
})
.switchMap(payload => this.APIcall(payload)
.then(data => {
const content = {};
data.items.map((item) => {
const slug = data.slug;
content[slug] = {
info: datasomeData
};
});
return new GetSomeContentSuccessAction({ categoryContent: categories });
})
.catch((err) => {
return new GetFailureAction({ error: {} });
})
);
Я хочу использовать какой-то оператор if или else для проверки магазина. Если данные существуют, я хочу отправить пустой объект обратно для редуктора, который я должен обработать. Если это не так, я хочу вызвать API и отправить эти данные обратно. Я не знаю, может ли наблюдаемое быть разветвленным другими словами, чтобы это можно было сделать?
Есть ли лучший способ, которым это могло быть достигнуто? Возможно, путем создания другого действия, чтобы иметь дело с API отдельно. Я хотел бы узнать, какова лучшая практика в будущем. Любая помощь будет принята с благодарностью.
1 ответ
Я просто работал над решением этой конкретной проблемы, поэтому я решил поставить свои 2 цента здесь на тот случай, если кто-то еще сочтет это полезным.
Есть отличная статья о том, как использовать NGRX-эффекты для этого. Это говорит о том, насколько сложно попытаться втиснуть это в цепочку эффектов ngrx.
Вместо этого они рекомендуют использовать сервис, который я использую и люблю. Простая версия может выглядеть следующим образом.
Service:
public posts$ = this.store.select(postSelectors.selectAll)
.pipe(
tap(posts => {
if (!posts.length) {
this.store.dispatch(new postActions.LoadMany());
}
}),
filter(posts => posts !== null)
);
Здесь мы в основном просто пытаемся выбрать часть состояния, которое нам нужно, и, если его там нет, отправляем действие, которое вызывает эффект, чтобы получить его из API и отправить его в магазин.
Component:
this.posts$ = this.postService.posts$;
Тогда в вашем компоненте вы можете просто подписаться на наблюдаемые из вашего сервиса и не заботиться о том, есть ли он в магазине или нет. Затем вы можете либо подписаться на это в своем компоненте, чтобы получить значение, либо отправить его в шаблон с асинхронным каналом.
Это очень хорошо работает для простых вещей, но я все еще работаю над более сложными цепочками RXJS для случаев, когда вам нужно получить данные, которые зависят от других данных, которые существуют в первую очередь. Но это всего лишь ограничение моих способностей при написании функций RXJS.