NGRX调用服务器就在最后
NGRX call server just at the end
在我的 Angular 应用程序中,我有一个效果(在应用程序启动时处理)从服务器检索可用语言。我要将 lang[] 保存在应用程序商店中保存的对象 (GlobalData) 中。
在登录组件中,我订阅了 属性 isFetchingLangs,一个布尔值,如果为真,它将禁用登录。
所以效果的步骤如下:
- 从商店获取 GlobalData
- 如果有语言,将 isFetchingLangs 设置为 false 并保存已创建 GlobalData 的事实;否则调用服务;
- 准备要分派的操作:如果 GlobalData 不存在,我添加语言并添加操作以保存 GlobalData。将 isFetchingLangs 设置为 false
这是代码:
coreActions$ = this.actions$
.ofType(CoreActions.GET_AVAILABLE_LANGS)
.pipe(
withLatestFrom(this.store.select(fromApp.getGlobalData))
, take(1)
, map(([action, storeState]) => {
if (storeState && storeState.langs && storeState.langs.length) {
this.globaDataCreated = true;
return this.store.dispatch(new CoreActions.GetAvailableLangsFinished());
} else {
return from(this.langsService.getAvailableLangs());
}
})
, mergeMap((langs: Lang[]) => {
let actions = [];
if (!this.globaDataCreated) {
this.applicationUrl = this.urlService.getApplicationUrl();
let newGlobalData = new GlobalData(
false,
null
);
langs.forEach(lang => {
newGlobalData.langs.push(lang)
});
this.translate.use('en');
this.moment.tz.setDefault("UTC");
actions.push({
type: CoreActions.SET_CORE_APPLICATION_DATA,
payload: newGlobalData
})
}
actions.push({
type: CoreActions.GET_AVAILABLE_LANGS_FINISHED
})
return actions;
})
, catchError((err, caught) => { ...... }
服务:
getAvailableLangs(): any {
return this.http.get<CommonClasses.SenecaResponse<CommonClasses.Lang[]>>(this.applicationData.applicationContext + 'rest-api/langs');
}
问题: 它在调用服务 this.langsService.getAvailableLangs() 之前进入 mergeMap((langs: Lang[]) => { ....}
目标: 等到 getAvailableLangs() 完成,然后将 isFetchingLangs 设置为 false 并进行其他操作
****** @JANRECKER 回答后编辑的代码 *********
getAvaibleLang(storeState?: GlobalData) {
if (storeState && storeState.langs && storeState.langs.length) {
return this.store.dispatch(new CoreActions.GetAvailableLangsFinished());
} else {
return this.langsService.getAvailableLangs();
}
}
@Effect()
coreActions$ = this.actions$
.ofType(CoreActions.GET_AVAILABLE_LANGS)
.pipe(
withLatestFrom(this.store.select(fromApp.getGlobalData))
, take(1)
, switchMap(([action, storeState]): Lang[] => this.getAvaibleLang(storeState))
, mergeMap(
(langs: Lang[]) => {
if (langs) {
const applicationUrl = this.urlService.getApplicationUrl();
let newGlobalData = new GlobalData(
applicationUrl,
false,
null
);
langs.forEach(lang => {
newGlobalData.langs.push(lang)
});
this.translate.use('en');
return [{
type: CoreActions.SET_CORE_APPLICATION_DATA,
payload: newGlobalData
}, {
type: CoreActions.GET_AVAILABLE_LANGS_FINISHED
}];
} else {
return [{
type: CoreActions.GET_AVAILABLE_LANGS_FINISHED
}];
}
}
)
, catchError((err, caught) => {....}
请注意,"map" 会更改流的内容。
of('helloWorld').pipe(
map((data:string):number => data.length) // data.length = 10
).subscribe(
(data:number) => console.log(data) ) // 10
)
你写了类似的东西(我用打字让它更明显一点)
of('helloWorld').pipe(
map((data:string):Observable<number> => from(data.length))
).subscribe(
(data:Observable<number>) => ... )
)
因此,您在可观察流中创建了一个可观察对象。 :-)
如果您想打开第二个流,"mergeMap" 将是正确的选择。
如果第一个流做了你想要的一切,而你现在想在不同的流上工作 "switchMap" 将是我的选择。
为了更好地理解代码,我会将流中的所有内容提取到方法中。像
coreActions$ = this.actions$
.ofType(CoreActions.GET_AVAILABLE_LANGS)
.pipe(
withLatestFrom(this.store.select(fromApp.getGlobalData))
, take(1)
,switchMap(([action,storeState]):Lang[] => this.getAvaibleLang(storeState) )
,tap(() => this.setApplicationUrl() )
,tap((langs:Lang[])=> this.setLanguages(langs) )
,tap(()=> this.pushLanguageAction() )
)
随着类型的大量使用,我认为它变得更具可读性。
热烈的问候
在我的 Angular 应用程序中,我有一个效果(在应用程序启动时处理)从服务器检索可用语言。我要将 lang[] 保存在应用程序商店中保存的对象 (GlobalData) 中。 在登录组件中,我订阅了 属性 isFetchingLangs,一个布尔值,如果为真,它将禁用登录。 所以效果的步骤如下:
- 从商店获取 GlobalData
- 如果有语言,将 isFetchingLangs 设置为 false 并保存已创建 GlobalData 的事实;否则调用服务;
- 准备要分派的操作:如果 GlobalData 不存在,我添加语言并添加操作以保存 GlobalData。将 isFetchingLangs 设置为 false
这是代码:
coreActions$ = this.actions$
.ofType(CoreActions.GET_AVAILABLE_LANGS)
.pipe(
withLatestFrom(this.store.select(fromApp.getGlobalData))
, take(1)
, map(([action, storeState]) => {
if (storeState && storeState.langs && storeState.langs.length) {
this.globaDataCreated = true;
return this.store.dispatch(new CoreActions.GetAvailableLangsFinished());
} else {
return from(this.langsService.getAvailableLangs());
}
})
, mergeMap((langs: Lang[]) => {
let actions = [];
if (!this.globaDataCreated) {
this.applicationUrl = this.urlService.getApplicationUrl();
let newGlobalData = new GlobalData(
false,
null
);
langs.forEach(lang => {
newGlobalData.langs.push(lang)
});
this.translate.use('en');
this.moment.tz.setDefault("UTC");
actions.push({
type: CoreActions.SET_CORE_APPLICATION_DATA,
payload: newGlobalData
})
}
actions.push({
type: CoreActions.GET_AVAILABLE_LANGS_FINISHED
})
return actions;
})
, catchError((err, caught) => { ...... }
服务:
getAvailableLangs(): any {
return this.http.get<CommonClasses.SenecaResponse<CommonClasses.Lang[]>>(this.applicationData.applicationContext + 'rest-api/langs');
}
问题: 它在调用服务 this.langsService.getAvailableLangs() 之前进入 mergeMap((langs: Lang[]) => { ....}
目标: 等到 getAvailableLangs() 完成,然后将 isFetchingLangs 设置为 false 并进行其他操作
****** @JANRECKER 回答后编辑的代码 *********
getAvaibleLang(storeState?: GlobalData) {
if (storeState && storeState.langs && storeState.langs.length) {
return this.store.dispatch(new CoreActions.GetAvailableLangsFinished());
} else {
return this.langsService.getAvailableLangs();
}
}
@Effect()
coreActions$ = this.actions$
.ofType(CoreActions.GET_AVAILABLE_LANGS)
.pipe(
withLatestFrom(this.store.select(fromApp.getGlobalData))
, take(1)
, switchMap(([action, storeState]): Lang[] => this.getAvaibleLang(storeState))
, mergeMap(
(langs: Lang[]) => {
if (langs) {
const applicationUrl = this.urlService.getApplicationUrl();
let newGlobalData = new GlobalData(
applicationUrl,
false,
null
);
langs.forEach(lang => {
newGlobalData.langs.push(lang)
});
this.translate.use('en');
return [{
type: CoreActions.SET_CORE_APPLICATION_DATA,
payload: newGlobalData
}, {
type: CoreActions.GET_AVAILABLE_LANGS_FINISHED
}];
} else {
return [{
type: CoreActions.GET_AVAILABLE_LANGS_FINISHED
}];
}
}
)
, catchError((err, caught) => {....}
请注意,"map" 会更改流的内容。
of('helloWorld').pipe(
map((data:string):number => data.length) // data.length = 10
).subscribe(
(data:number) => console.log(data) ) // 10
)
你写了类似的东西(我用打字让它更明显一点)
of('helloWorld').pipe(
map((data:string):Observable<number> => from(data.length))
).subscribe(
(data:Observable<number>) => ... )
)
因此,您在可观察流中创建了一个可观察对象。 :-)
如果您想打开第二个流,"mergeMap" 将是正确的选择。 如果第一个流做了你想要的一切,而你现在想在不同的流上工作 "switchMap" 将是我的选择。
为了更好地理解代码,我会将流中的所有内容提取到方法中。像
coreActions$ = this.actions$
.ofType(CoreActions.GET_AVAILABLE_LANGS)
.pipe(
withLatestFrom(this.store.select(fromApp.getGlobalData))
, take(1)
,switchMap(([action,storeState]):Lang[] => this.getAvaibleLang(storeState) )
,tap(() => this.setApplicationUrl() )
,tap((langs:Lang[])=> this.setLanguages(langs) )
,tap(()=> this.pushLanguageAction() )
)
随着类型的大量使用,我认为它变得更具可读性。
热烈的问候