过滤两个可观察对象的正确方法
Correct way of filtering two observable
我的任务是根据另外两个列表获取可观察列表。这是有效的代码,但我想知道它是否可以(也从性能角度来看):
get availableCodeValueLanguages$(): Observable<Common.Lookup<string>[]> {
return this.languageCodesLookupData$.pipe(
withLatestFrom(this.languageData$),
map(([lookupLanguages, codeValues]) => {
const codeValueLanguageCodes = codeValues.map(codeValue => codeValue.language.id);
return lookupLanguages.filter(lookupLanguage =>
!codeValueLanguageCodes.includes(lookupLanguage.id));
}),
catchError(error => {
return of([]);
})
)
}
languageData$ 包含 grid 的数据。它是一个复杂属性 CodeValue 的列表,每个属性都包含不同的 Language。 languageCodesLookupData$ 是所有可用 language 的完整列表。 availableCodeValueLanguages$ 需要为 dropdownlist 包含 language,只需要添加一个即可语言 CodeValue form.
languageCodesLookupData$ 在 Component Init 上加载(极不可能在使用页面时发生变化)。相应地,一旦我们将新条目添加到 form 中的 CodeValue 列表中,languageData$ 就会发生变化。
从性能的角度来看,您的代码看起来不错,使用 withLatestFrom
是组合流的典型方式。
然而...
languageCodesLookupData$ is loaded on Component Init (highly unlikely it's gonna change during working with a page)
使用 withLatestFrom
只会在源 observable 发出时发出。
languageData$ is changed once we add a new entry to the CodeValue list in the form.
所以,我假设您在发生这种情况时会想要 availableCodeValueLanguages$
。
如果是这种情况,您应该使用 combineLatest
:
availableCodeValueLanguages$ = combineLatest(
this.languageCodesLookupData$,
this.languageData$
).pipe(
map(([lookupLanguages, codeValues]) => {
const codeValueLanguageCodes = codeValues.map(codeValue => codeValue.language.id);
return lookupLanguages.filter(lookupLanguage =>
!codeValueLanguageCodes.includes(lookupLanguage.id));
}),
catchError(error => {
return of([]);
})
);
如果需要,您可以将 codeValueLanguageCodes
定义为它自己的可观察对象。
codeIds$ = this.languageData$.pipe(
map(codeValue => codeValue.language.id)
);
availableCodeValueLanguages$ = combineLatest(
this.languageCodesLookupData$,
this.codeIds$
).pipe(
map(([languages, codeIds]) => languages.filter(
language => !codeIds.includes(language.id));
),
catchError(error => {
return of([]);
})
);
我的任务是根据另外两个列表获取可观察列表。这是有效的代码,但我想知道它是否可以(也从性能角度来看):
get availableCodeValueLanguages$(): Observable<Common.Lookup<string>[]> {
return this.languageCodesLookupData$.pipe(
withLatestFrom(this.languageData$),
map(([lookupLanguages, codeValues]) => {
const codeValueLanguageCodes = codeValues.map(codeValue => codeValue.language.id);
return lookupLanguages.filter(lookupLanguage =>
!codeValueLanguageCodes.includes(lookupLanguage.id));
}),
catchError(error => {
return of([]);
})
)
}
languageData$ 包含 grid 的数据。它是一个复杂属性 CodeValue 的列表,每个属性都包含不同的 Language。 languageCodesLookupData$ 是所有可用 language 的完整列表。 availableCodeValueLanguages$ 需要为 dropdownlist 包含 language,只需要添加一个即可语言 CodeValue form.
languageCodesLookupData$ 在 Component Init 上加载(极不可能在使用页面时发生变化)。相应地,一旦我们将新条目添加到 form 中的 CodeValue 列表中,languageData$ 就会发生变化。
从性能的角度来看,您的代码看起来不错,使用 withLatestFrom
是组合流的典型方式。
然而...
languageCodesLookupData$ is loaded on Component Init (highly unlikely it's gonna change during working with a page)
使用 withLatestFrom
只会在源 observable 发出时发出。
languageData$ is changed once we add a new entry to the CodeValue list in the form.
所以,我假设您在发生这种情况时会想要 availableCodeValueLanguages$
。
如果是这种情况,您应该使用 combineLatest
:
availableCodeValueLanguages$ = combineLatest(
this.languageCodesLookupData$,
this.languageData$
).pipe(
map(([lookupLanguages, codeValues]) => {
const codeValueLanguageCodes = codeValues.map(codeValue => codeValue.language.id);
return lookupLanguages.filter(lookupLanguage =>
!codeValueLanguageCodes.includes(lookupLanguage.id));
}),
catchError(error => {
return of([]);
})
);
如果需要,您可以将 codeValueLanguageCodes
定义为它自己的可观察对象。
codeIds$ = this.languageData$.pipe(
map(codeValue => codeValue.language.id)
);
availableCodeValueLanguages$ = combineLatest(
this.languageCodesLookupData$,
this.codeIds$
).pipe(
map(([languages, codeIds]) => languages.filter(
language => !codeIds.includes(language.id));
),
catchError(error => {
return of([]);
})
);