过滤两个可观察对象的正确方法

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 的列表,每个属性都包含不同的 LanguagelanguageCodesLookupData$ 是所有可用 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([]);
  })
);