NgRx:多次调用 CustomRouterStateSerializer serialize()
NgRx: CustomRouterStateSerializer serialize() called multiple times
我已经以常用方式 (https://ngrx.io/guide/router-store/configuration) 为我的 Angular 项目实现了一个 NgRx Router-Store。
我的 "Problem" 是我的 CustomRouterStateSerializer
的序列化方法似乎被多次调用,当通过单击组件的相应 html 元素触发 routerLink 时。
您将在 StackBlitz.
上找到以下描述的最小示例应用程序
我的实现
这是我的 router.reducer.ts
文件,其中包含 RouterStateUrl-Interface 和 Serializer-Class:
export interface RouterStateUrl {
url: string;
queryParams: Params;
params: Params;
random: number;
}
export class CustomRouterStateSerializer implements RouterStateSerializer<RouterStateUrl > {
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
const { url, root: { queryParams } } = routerState;
// Random number to be able to match console output to router-state later (with NgRx Store DevTools)
const random = Math.random();
console.warn(`CustomRouterStateSerializer called by ${url}, random: ${random}`);
let state: ActivatedRouteSnapshot = routerState.root;
while(state.firstChild){
state = state.firstChild;
}
const { params } = state;
return {url, queryParams, params, random };
}
}
这是我的 app.module.ts
文件:
/*[...]*/
imports: [
/*[...],*/
StoreModule.forRoot(reducers, {
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true
}
}),
StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.development }),
EffectsModule.forRoot([AppEffects]),
StoreRouterConnectingModule.forRoot({
serializer: CustomRouterStateSerializer,
navigationActionTiming: NavigationActionTiming.PostActivation,
}),
]
/*[...]*/
详细描述和输出
假设我的应用程序当前显示一些项目的概览 (url: /projects) 并且触发 routerLink 以切换组件以显示作业概览 (url: /jobs ).控制台将打印三个消息:
CustomRouterStateSerializer called by /projects, random: 0.0896547559010431
CustomRouterStateSerializer called by /jobs, random: 0.7662025752972623
CustomRouterStateSerializer called by /jobs, random: 0.07919176016307328
NgRx Store DevTools 正在按预期显示多个操作:
@ngrx/router-store/request
router: {
state: {
url: '/projects',
queryParams: {},
params: {},
random: 0.31957045879116797
},
navigationId: 2
}
@ngrx/router-store/navigation
router: {
state: {
url: '/jobs',
queryParams: {},
params: {},
random: 0.7662025752972623
},
navigationId: 3
}
@ngrx/router-store/navigated
router: {
state: {
url: '/jobs',
queryParams: {},
params: {},
random: 0.7662025752972623
},
navigationId: 3
}
如您所见,@ngrx/router-store/navigation
和 @ngrx/router-store/navigated
的状态相同。此外,它们的随机数与第二个控制台输出相同。 @ngrx/router-store/request
的随机数属于旧projects-view的状态
NgRx Store DevTools 的输出似乎符合预期。但我不明白何时以及什么调用了其他控制台输出被触发的序列化方法。我在任何状态下都找不到第一个和第三个控制台输出的任何随机数。现在我问自己是不是我犯了错误(实现东西)或者这是否只是正常行为(但为什么?)。也许你们中的一些人可以告诉我。
我尝试了一些东西,但最终还是有助于查看 @ngrx/router-store
的源代码。
这个模块本质上做的是监听所有的路由器事件和派发动作。重要的一段代码是:https://github.com/ngrx/platform/blob/master/modules/router-store/src/router_store_module.ts#L240-L275
But I don't understand when and what called the serialize method where the other console outputs were triggert.
这里可以看到可以调用serialize()
的三种情况:
- 在
NavigationStart
(直接)
- 在
NavigationEnd
(通过 dispatchRouterNavigation()
和 dispatchRouterNavigated()
方法)
- 在
RoutesRecognized
(通过 dispatchRouterNavigated()
)
这些事件中的每一个都单独调用 serialize()
以避免派生状态:路由器是路由器状态的来源,它可以随时更改。
因此,当需要序列化状态时,它不会存储在某个地方,而是每次都重新计算。
这就是多次调用该函数的原因。但是,由于序列化器函数应该是纯函数,所以这根本不是问题,而是设计的一部分。
I can not find any random numbers of the first and the third console output in any state.
reducer 只会将路由器状态放入 navigation
、cancel
和 error
的存储中 – 但不会在 request
和 navigated
。
这意味着,您在商店中看到的唯一随机数是来自 navigation
操作的随机数。
所有其他的都只是使用 "on the way".
Now I'm asking myself if I have made an error (implementing stuff) or if this is just normal behaviour (but why?).
您的实施看起来不错,您可以放心:这是正常的预期行为!请注意,您的序列化程序函数应该是纯的。
希望对您有所帮助!
我已经以常用方式 (https://ngrx.io/guide/router-store/configuration) 为我的 Angular 项目实现了一个 NgRx Router-Store。
我的 "Problem" 是我的 CustomRouterStateSerializer
的序列化方法似乎被多次调用,当通过单击组件的相应 html 元素触发 routerLink 时。
您将在 StackBlitz.
上找到以下描述的最小示例应用程序我的实现
这是我的 router.reducer.ts
文件,其中包含 RouterStateUrl-Interface 和 Serializer-Class:
export interface RouterStateUrl {
url: string;
queryParams: Params;
params: Params;
random: number;
}
export class CustomRouterStateSerializer implements RouterStateSerializer<RouterStateUrl > {
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
const { url, root: { queryParams } } = routerState;
// Random number to be able to match console output to router-state later (with NgRx Store DevTools)
const random = Math.random();
console.warn(`CustomRouterStateSerializer called by ${url}, random: ${random}`);
let state: ActivatedRouteSnapshot = routerState.root;
while(state.firstChild){
state = state.firstChild;
}
const { params } = state;
return {url, queryParams, params, random };
}
}
这是我的 app.module.ts
文件:
/*[...]*/
imports: [
/*[...],*/
StoreModule.forRoot(reducers, {
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true
}
}),
StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.development }),
EffectsModule.forRoot([AppEffects]),
StoreRouterConnectingModule.forRoot({
serializer: CustomRouterStateSerializer,
navigationActionTiming: NavigationActionTiming.PostActivation,
}),
]
/*[...]*/
详细描述和输出
假设我的应用程序当前显示一些项目的概览 (url: /projects) 并且触发 routerLink 以切换组件以显示作业概览 (url: /jobs ).控制台将打印三个消息:
CustomRouterStateSerializer called by /projects, random: 0.0896547559010431
CustomRouterStateSerializer called by /jobs, random: 0.7662025752972623
CustomRouterStateSerializer called by /jobs, random: 0.07919176016307328
NgRx Store DevTools 正在按预期显示多个操作:
@ngrx/router-store/request
router: {
state: {
url: '/projects',
queryParams: {},
params: {},
random: 0.31957045879116797
},
navigationId: 2
}
@ngrx/router-store/navigation
router: {
state: {
url: '/jobs',
queryParams: {},
params: {},
random: 0.7662025752972623
},
navigationId: 3
}
@ngrx/router-store/navigated
router: {
state: {
url: '/jobs',
queryParams: {},
params: {},
random: 0.7662025752972623
},
navigationId: 3
}
如您所见,@ngrx/router-store/navigation
和 @ngrx/router-store/navigated
的状态相同。此外,它们的随机数与第二个控制台输出相同。 @ngrx/router-store/request
的随机数属于旧projects-view的状态
NgRx Store DevTools 的输出似乎符合预期。但我不明白何时以及什么调用了其他控制台输出被触发的序列化方法。我在任何状态下都找不到第一个和第三个控制台输出的任何随机数。现在我问自己是不是我犯了错误(实现东西)或者这是否只是正常行为(但为什么?)。也许你们中的一些人可以告诉我。
我尝试了一些东西,但最终还是有助于查看 @ngrx/router-store
的源代码。
这个模块本质上做的是监听所有的路由器事件和派发动作。重要的一段代码是:https://github.com/ngrx/platform/blob/master/modules/router-store/src/router_store_module.ts#L240-L275
But I don't understand when and what called the serialize method where the other console outputs were triggert.
这里可以看到可以调用serialize()
的三种情况:
- 在
NavigationStart
(直接) - 在
NavigationEnd
(通过dispatchRouterNavigation()
和dispatchRouterNavigated()
方法) - 在
RoutesRecognized
(通过dispatchRouterNavigated()
)
这些事件中的每一个都单独调用 serialize()
以避免派生状态:路由器是路由器状态的来源,它可以随时更改。
因此,当需要序列化状态时,它不会存储在某个地方,而是每次都重新计算。
这就是多次调用该函数的原因。但是,由于序列化器函数应该是纯函数,所以这根本不是问题,而是设计的一部分。
I can not find any random numbers of the first and the third console output in any state.
reducer 只会将路由器状态放入 navigation
、cancel
和 error
的存储中 – 但不会在 request
和 navigated
。
这意味着,您在商店中看到的唯一随机数是来自 navigation
操作的随机数。
所有其他的都只是使用 "on the way".
Now I'm asking myself if I have made an error (implementing stuff) or if this is just normal behaviour (but why?).
您的实施看起来不错,您可以放心:这是正常的预期行为!请注意,您的序列化程序函数应该是纯的。
希望对您有所帮助!