如何 return 从单个 Observable<[]> 修改两个 Observable<[]>

How to return two modified Observable<[]> from a single Observable<[]>

我有一个 Observable<Person[]>,其中 Person 界面如下所示:

export interface ToolfaceData {
    age: number;
    name: string;
}

我想创建两个 Observable<Person[]>,其中一个将 2 添加到数组中所有 Person 的年龄,另一个从数组中减去 2数组中所有 Person 的年龄。

如果这是流式传输给我的数据: of (Person{age:2, name: Anne}, Person{age:5, name: Bob}),然后我会创建两个 Observable<Person[]>
of (Person{age:4, name: Anne}, Person{age:7, name: Bob})of (Person{age:0, name: Anne}, Person{age:3, name: Bob})

我该怎么做呢?

我尝试过的:

  1. 我已经尝试 tap 并发现当我只创建两个 observable 之一时,它可以工作,但是当我创建两个时,它们都是原始的 Observable(我不确定为什么会这样,但我想这不是我现在的主要问题)。
  2. 我已经尝试 map 但找不到在创建第一个 observable 时不修改原始数据的方法,这在我尝试创建第二个 observable 时会产生问题。

我不确定你的意图,但是...

tap 仅用于副作用,实际上它对可观察管道根本没有影响。它用于例如用于调试或记录。

map 用于将传递的值重新映射到另一个值。例如。你可以像 .pipe(map(person => Person{age: person + 2, name: person.name}))

这样给 Person 添加年龄

mergeMap 用于将传递的值重新映射到新的可观察对象,其值将传递到输出流。它用于例如对于异步 API 调用。

所以您尝试做的可能是这样的:

source$.pipe(
  mergeMap(person => concat( // concat two observables
    of(Person{age: person + 2, name: person.name}), // .pipe(...),
    of(Person{age: person - 2, name: person.name}) // .pipe(...)
  ))
)

concat, like merge or race 的替代方法。这取决于您想要的行为。

您可以将一个初始的 Observable 数据流分配给一个新的 observable 变量,使用管道运算符修改数据并单独订阅该值,而无需修改原始源数据。

我用地图函数给年龄加了2

const personObservable$ = of(
  {
    age: 2,
    name: 'Anne',
  },
  {
    age: 5,
    name: 'Bob',
  }
);

personObservable$.subscribe(person => console.log('Original', person));

const personAgePlus$ = personObservable$
  .pipe(
    map(({age, name}) => {
      age = age + 2;
      return {age, name};
    })
  ).subscribe(person => console.log('Age +2', person));


const personAgeMinus$ = personObservable$
  .pipe(
    map(({age, name}) => {
      age = age - 2;
      return {age, name};
    })
  ).subscribe(person => console.log('Age -2', person));


如果您希望从现有的可观察对象创建一个(或更多)可观察对象,您可以简单地将其定义为从原始对象开始,然后pipe()排放到您想要的值。

因此,如果您的“原始”值如下所示:

people$ = this.service.getPeople();

您可以像这样定义其他可观察对象:

olderPeople$ = this.people$.pipe(
  map(people => people.map(p => ({...p, age: p.age + 2})))
);

youngerPeople$ = this.people$.pipe(
  map(people => people.map(p => ({...p, age: p.age - 2})))
);

这是一个有效的 StackBlitz 演示。


注意:如果多个 observables 来自同一来源,您可以将 shareReplay 应用于原始数据以防止底层逻辑(在这种情况下调用 getPeople()) 从为每个订阅执行一次:

people$ = this.service.getPeople().pipe(shareReplay());