如何使用@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
目前,我想在我的项目中使用 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