Прежде чем получать новые данные из серверной части, я сначала проверяю, есть ли они уже в магазине, и всегда забочусь о том, чтобы магазин всегда синхронизировался при каждом обновлении.
Для этого мой effect
делает следующее:
@Effect()
LoadImage: Observable<LoadImageSuccess> = this.actions$.pipe(
ofType(AppActionTypes.LOAD_IMAGE),
withLatestFrom(action => this.store$.select(selectImage, action.payload).pipe(map(result => ({ action, result })))),
switchMap(observable => observable),
mergeMap(({ action, result }) =>
result !== null
? of(result).pipe(map(image => new LoadImageSuccess(image)))
: this.imageApiService.getImage(action.payload).pipe(
map(image => new LoadImageSuccess(image)),
catchError(error => EMPTY)
)
)
);
Кажется, это работает нормально, но мне интересно, можно ли это сделать лучше:
switchMap(observable => observable),
выглядит не очень красиво.mergeMap
лучше обрабатываться через iif
?LOAD_IMAGE
, мой вызов API все еще происходит дважды, потому что первый запрос еще не завершен (и не поместил изображение в хранилище), когда начинается второй запрос. Это не обычное явление с изображениями на моем веб-сайте, но может быть с другими компонентами в будущем, и мне интересно, есть ли способ улучшить это.Спасибо!
Обратите внимание, если я удалю switchMap(observable => observable),
, я получу следующую ошибку:
Объект, который передается mergeMap
, если я закомментирую switchMap
, имеет тип Store
:
Обновлено:
Основываясь на принятом ответе, вот что у меня получилось:
@Effect()
LoadImage: Observable<LoadImageSuccess> = this.actions$.pipe(
ofType(AppActionTypes.LOAD_IMAGE),
mergeMap(action =>
this.store$.select(selectImage, action.payload).pipe(
mergeMap(imageFromStore =>
imageFromStore !== null
? of(imageFromStore).pipe(map(image => new LoadImageSuccess(image)))
: this.imageApiService.getImage(action.payload).pipe(
map(image => new LoadImageSuccess(image)),
catchError(error => EMPTY)
)
)
)
)
);
@MikeOne, потому что withLatestFrom
над ним возвращает Observable<{LoadImageSuccess, Image}>
.
Карта слияния ниже также подпишется на это..?
@MikeOne Я отредактировал вопрос, чтобы показать, что произойдет, если я удалю это switchMap
.
Да это ожидаемо. Теперь вы получите массив. Удалите деструктуру с помощью «данных» или чего-то еще и утешьте ее.
@MikeOne Я обновил вопрос, смотрите в конце. То, что я получаю в mergeMap
, относится к типу Store
.
Проблема в том, что аргумент, переданный withLatestFrom
, является проекционной функцией, поэтому вам приходится прибегать к хаку switchMap
.
Если вам нужно проверить на основе текущего действия, я думаю, вам лучше сделать это примерно так:
ofType(...),
// do the check
switchMap(
action => this.store.select(...)
.pipe(
...,
// act based on the check's result
// decided to nest this as a response to question 3
// since if multiple calls are made at the same time, only the last one will be good to go
switchMap(({ action, result }) => ...)
)
),
Почему этот switchMap вообще там...?