如何使用@NgRx/effects 只向服务器发送一次请求

How to send request to the server only once by using @NgRx/effects

目前,我想在我的项目中使用 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组件时,我都会向服务器发送请求?

如果是,我如何配置我的效果只发送一次请求?

或者这种情况下最好的方法是什么?

任何帮助将不胜感激。

谢谢!

因此,您可以尝试的方法是将 API 响应保存在 sessionStorage 中,并在用户导航到 ToDoComponent 时检查会话存储中响应的可用性。

是的,每次您导航到该组件时,它都会获取待办事项。

这是调度线的原因,

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

您可以检查它是否已出现在商店中,如 Start using ngrx/effects for this

中所示
@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)
    )
  );

这里是 stackblitz 示例。 https://stackblitz.com/edit/angular-d6jctm