NGXS, лучший способ отправить запуск, успешное или неудачное действие из одного и того же действия?

У меня есть следующий код для получения всех моих сообщений

`    @Action(actions.FetchPosts)
    fetchAll(ctx: StateContext<PostStateModel>){
        return this.postService.fetchPosts().pipe(tap((postsResults) => {
            const state = ctx.getState();
                ctx.patchState({
                ...state,
                posts: [                    
                    ...postsResults                    
                ],                
            })
        }),
        mergeMap(() => {
          console.log("Inside of mergeMap")
          return ctx.dispatch(new actions.FetchPostsSuccess())
        }),      
        catchError(err => 
        {
          console.log("Inside of catchError")
          return ctx.dispatch(new actions.FetchPostsFail(err))
        }
      ))
    }`

Это работает, однако я хочу выполнить еще одну отправку, прежде чем звонить в мою почтовую службу. Как лучше всего использовать асинхронное программирование, чтобы убедиться, что я сначала отправлю действие start, которое установит для свойства загрузки значение true, а затем убедитесь, что я вызываю только успешный вызов только после успешного возврата запроса.

Кроме того, следуя документации ngxs, я использую mergeMap (), который, похоже, выполняет свою работу. Мне любопытно, однако, postService, который возвращает массив сообщений, возвращает один наблюдаемый или один наблюдаемый объект, который затем испускает несколько наблюдаемых более высокого порядка (внутренние наблюдаемые)?


person O.MeeKoh    schedule 11.02.2019    source источник
comment
Нет необходимости отправлять другое действие только для того, чтобы обновить загрузку до значения true. вы используете существующее действие FetchPost для обновления состояния.   -  person Sadid Khan    schedule 11.02.2019


Ответы (1)


Вы можете начать с отправки действия загрузки:

@Action(actions.FetchPosts)
fetchAll(ctx: StateContext<PostStateModel>){
    return ctx.dispatch(new ChangeLoadingToInProgress()).pipe(
      mergeMap(() => this.postService.fetchPosts()),
      tap((postsResults) => {
        const state = ctx.getState();
            ctx.patchState({
            ...state,
            posts: [                    
                ...postsResults                    
            ],                
        })
    }),
    mergeMap(() => {
      console.log("Inside of mergeMap")
      return ctx.dispatch(new actions.FetchPostsSuccess())
    }),      
    catchError(err => 
    {
      console.log("Inside of catchError")
      return ctx.dispatch(new actions.FetchPostsFail(err))
    }
  ))
}

или я считаю, что вы можете сразу изменить состояние:

@Action(actions.FetchPosts)
fetchAll(ctx: StateContext<PostStateModel>){
    ctx.patchState({ loading: true });
    return this.postService.fetchPosts().pipe(tap((postsResults) => {
        const state = ctx.getState();
            ctx.patchState({
            ...state,
            posts: [                    
                ...postsResults                    
            ],                
        })
    }),
    mergeMap(() => {
      console.log("Inside of mergeMap")
      return ctx.dispatch(new actions.FetchPostsSuccess())
    }),      
    catchError(err => 
    {
      console.log("Inside of catchError")
      return ctx.dispatch(new actions.FetchPostsFail(err))
    }
  ))
}
person Martin Nuc    schedule 11.02.2019
comment
Оба эти ответа имеют смысл. У меня была вторая реализация, но я не был уверен, что это правильно. Я думал, что должен сделать то же, что и вы в первом примере. Кроме того, не следует ли мне использовать switchMap для обоих? Поскольку mergemap поддерживает внутреннюю подписку, где был switchMap, будет подписываться только на внутреннюю наблюдаемую до тех пор, пока не будет выпущена новая? Поскольку я получаю все сообщения, я думаю, что switchMap - это то, что мне нужно для отправки обоих. Вы бы согласились? - person O.MeeKoh; 11.02.2019
comment
@ O.MeeKoh ты прав насчет карты переключения. Определенно должно быть mergeMap. Что касается того, какой подход выбрать - я бы выбрал второй. Но это действительно зависит от вас, если вы хотите иметь действие для переключения состояния загрузки. Имхо это привело бы к взрыву действий. Также мне не нравится порядок действий, когда вы смотрите в инструменты redux-dev - порядок неправильный. Для этого есть ошибка, но в настоящее время я не вижу никаких преимуществ в создании отдельного действия для переключения состояния isLoading. - person Martin Nuc; 11.02.2019
comment
@ O.MeeKoh и еще кое-что - я бы лично исправил состояние при успехе в обработчике FetchPostsSuccess. postResults должен быть imho передан действию как полезная нагрузка. - person Martin Nuc; 11.02.2019
comment
Да, это хороший момент. Я обязательно выполню оба этих совета. Кроме того, знаете ли вы, почему «определенно» должно быть mergeMap? Не уверен, что вижу полную картину, так как не уверен, что использовать. - person O.MeeKoh; 11.02.2019
comment
Ой, подождите, похоже, здесь это не имеет значения. Разница в том, что switchMap отменяет подписку на внутреннее наблюдаемое при новой передаче. Поскольку вы всегда создаете новую наблюдаемую, не имеет значения, какую из них вы используете. Однако, если вы использовали ngrx (у вас есть ngxs) с actions$.pipe(ofType(...)), новое действие отменит старое с помощью switchMap. Например, если у вас есть кнопка перезагрузки, и вы нажимаете ее больше времени, mergeMap вызовет несколько запросов, switchMap отменит предыдущий. Зависит от вашего использования. - person Martin Nuc; 11.02.2019
comment
Отлично, теперь ясно. Итак, вообще говоря, когда вы отправляете запрос на бэкэнд-сервер, и сервер отвечает одним запросом (массивом элементов), этот единственный запрос обрабатывается как один наблюдаемый, и в этом случае никакие внутренние наблюдаемые не испускаются правильно? - person O.MeeKoh; 11.02.2019
comment
Это больше вопрос о том, хотите ли вы одновременно только один запрос вверх или нет. Представьте, что вы должны отправить позицию мыши в заданное время - тогда вы хотите, чтобы все ваши запросы приходили на сервер. Когда один из них задерживается из-за проблем с сетью, вам все равно. Но если у вас есть кнопка «Обновить продукты», и пользователь дважды щелкает мышью, вы хотите, чтобы был только один запрос, а другой был отменен, чтобы не было состояния гонки. - person Martin Nuc; 11.02.2019