Как отправить запрос на сервер только один раз, используя @ NgRx / Effects - PullRequest
1 голос
/ 20 января 2020

В настоящее время я хочу использовать NgRx в своем проекте, и у меня есть вопрос, связанный с получением данных с сервера.

Например, у меня есть этот код.

в компоненте

// import ....

export class ToDoComponent implements OnInit {
  todo$: Observable<ToDoState>;
  ToDoSubscription: Subscription;
  ToDoList: ToDo[] = [];

  constructor(private store: Store<{ todos: ToDoState }>) {
    this.todo$ = store.pipe(select('todos'));
  }

  ngOnInit() {
    this.ToDoSubscription = this.todo$
      .pipe(
        map(x => {
          this.ToDoList = x.ToDos;
          this.todoError = x.ToDoError;
        })
      )
      .subscribe();

    this.store.dispatch(ToDoActions.BeginGetToDoAction());
  }
}

и этот

в эффектах

// import ....

@Injectable()
export class ToDoEffects {
  constructor(private http: HttpClient, private action$: Actions) {}

  private ApiURL: string = 'https://localhost:44308/api/ToDo';

  GetToDos$: Observable<Action> = createEffect(() =>
    this.action$.pipe(
      ofType(ToDoActions.BeginGetToDoAction),
      mergeMap(action =>
        this.http.get(this.ApiURL).pipe(
          map((data: ToDo[]) => {
            return ToDoActions.SuccessGetToDoAction({ payload: data });
          }),
          catchError((error: Error) => {
            return of(ToDoActions.ErrorToDoAction(error));
          })
        )
      )
    )
  );
}

Означает ли это, что я отправлю запрос на сервер каждый раз, когда пользователь переходит на компонент ToDoComponent?

Если да, как я могу настроить свой эффект для отправки запроса только один раз?

Или как лучше всего этот случай?

Любая помощь будет оценена.

Спасибо!

Ответы [ 2 ]

1 голос
/ 20 января 2020

Да, каждый раз, когда вы переходите к компоненту, он выбирает задачу.

Это из-за строки отправки,

this.store.dispatch(ToDoActions.BeginGetToDoAction());

Вы можете проверить, присутствует ли она уже в магазине как показано в Начните использовать ngrx / эффекты для этого

@Effect()
getOrder = this.actions.pipe(
  ofType<GetOrder>(ActionTypes.GetOrder),
  withLatestFrom(action =>
    of(action).pipe(
      this.store.pipe(select(getOrders))
    )
  ),
  filter(([{payload}, orders]) => !!orders[payload.orderId])
  mergeMap([{payload}] => {
    ...
  })
)

Или вы можете просто добавить take(1) в свой эффект:

  GetToDos$: Observable<Action> = createEffect(() =>
    this.action$.pipe(
      ofType(ToDoActions.BeginGetToDoAction),
      mergeMap(action =>
        this.http.get(this.ApiURL).pipe(
          map((data: ToDo[]) => {
            return ToDoActions.SuccessGetToDoAction({ payload: data });
          }),
          catchError((error: Error) => {
            return of(ToDoActions.ErrorToDoAction(error));
          })
        )
      ),
      take(1)
    )
  );

вот Пример стекаблица. https://stackblitz.com/edit/angular-d6jctm

0 голосов
/ 20 января 2020

Итак, подход, который вы можете попробовать, - это сохранить ответ API в sessionStorage и проверить доступность ответа в хранилище сеанса, когда пользователь переходит к ToDoComponent.

...