RxJS - 条件连接并合并来自响应的对象

RxJS - Conditional Concat and merge objects from response

我目前正在开发一个 ionic 5 应用程序,我有 2 个可观察对象,它们 return 有 2 个不同对象类型的数组。 我想将对象的一些属性混合在一个新类型的对象中,但我只想在第一个 returns 值时对服务器进行第二次调用。

示例:

obs1$: Observable<{id: string, name: string, active: boolean}[]>;
obs2$: Observable<{id: string, location: Location, year: date}[]>;

newObs$: Observable<{id: string, name: string, year: date}[]>;

我要:

  1. 致电obs1$
  2. 如果 obs1$ returns 值则调用 obs2$,否则 returns []
  3. obs2$ returns 值时,return 对象数组映射两个可观察对象的结果

我猜你在 class。你可以这样做。但是请确保在映射之前初始化您的可观察对象。

  obs1$: Observable<{ id: string; name: string; active: boolean }[]>; 
  obs2$: Observable<{ id: string; location: Location; year: Date }[]>;

  newObs$ = this.obs1$.pipe(
    switchMap((item) => {
      const emptyArray: { id: string; name: string; year: Date }[] = [];
      return item? this.obs2$.pipe(
            map((item2) => {
              const others = item2.map((ent2) => {
                const index = item.findIndex(ent1 => ent1.id === ent2.id)
                let name = ''

                if(index !== -1){
                  name = item[index].name
                }
                const id = ent2.id;
                const year = ent2.year;
                return {name, id, year}
              });

              return others
            }),
          )
        : of(emptyArray);
    }),
  );

我添加了一些接口以使代码更易于阅读。我在这里假设您的第一个可观察 returns 没有值时是一个空数组。如果它 returns null 而不是,您可能想要删除 switchMap.

中的 .length

下面的代码工作得很好。

interface First {
  id: string;
  name: string;
  active: boolean;
}
interface Second {
  id: string;
  location: Location;
  year: Date;
}
interface Result {
  id: string;
  name: string;
  year: Date;
}

...
const first$: Observable<First[]>;    // Make sure it's initialized
const second$: Observable<Second[]>;  // Make sure it's initialized
...

const result$: Observable<Result[]> = first$.pipe(
  switchMap(firstArray => !firstArray.length
    ? of([])
    : second$.pipe(
        map(secondArray => firstArray
          .filter(a => secondArray.some(b => a.id === b.id))
          .map(a => ({ first: a, second: secondArray.find(b => a.id === b.id) }))
          .map(values => ({...values.first, year: values.second.year }))
        )
    )
  )
);