在Angular2+中向rxjs BehaviorSubject或Subject的数组中添加元素

3
我在学习Angular的“无关组件:使用服务共享数据”部分时,阅读了有关如何在不相关的组件之间共享数据的内容。教程链接在这里。我明白他们的示例是如何共享字符串类型的数据,但我的数据类型稍微复杂一些。具体来说,我认为我的BehaviorSubject应该像这样:
private currentPopulationSource: BehaviorSubject<Population> = new BehaviorSubject<Population>(new Population(new Array<Organism>()));

我的人口模型只是一个包含生物数组的容器:
import { Organism } from './organism.model';

export class Population {
  private individuals: any;
  constructor(individuals: Organism[]){
     this.individuals = individuals;
  }

  getIndividuals(){
    return this.individuals;
  }
}

我有一个名为organism1的Organism实例。

我想将它添加到Population模型中的individuals数组中,并希望多个不相关的组件订阅population BehaviorSubject(我目前在我的PopulationManagerService中声明currentPopulationSource后面有private currentPopulation = this.currentPopulationSource.asObservable();,就像我在教程中看到的那样)。

对我来说不清楚将organism1添加到currentPopulationSource中的语法是什么(.next()在这里似乎没有意义)。

也许BehaviorSubject并不是在这里做出最恰当的选择,如果我想要一个不断增长的数组作为发射的东西?如果有更好的选择(ReplaySubject?),我不太知道如何实现它。

我的人口管理服务:

import { Injectable } from '@angular/core';
import { Organism } from './organism.model';
import { Population } from './population.model';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PopulationManagerService {
  private currentPopulationSource: BehaviorSubject<Population> = new BehaviorSubject<Population>(new Population(new Array<Organism>()));
  currentPopulation = this.currentPopulationSource.asObservable();
  constructor() { }

  addOrganismToPopulation(organism: Organism){
    this.currentPopulationSource.next(new Population(new Array<Organism>(organism))); //This does not work
    // this.currentPopulation.getIndividuals().push(organism); //This did not work either, because currentPopulation is of type Observable<Population> rather than of type Population
  }
}

在我的组件中:
let testIndividual: Organism = this.individualGenService.makeIndividual("green", "blue");
    this.popManager.addOrganismToPopulation(testIndividual);
    this.popManager.currentPopulation.subscribe(results =>{
      console.log(results.getIndividuals()); //returns undefined
    });

目前返回的是未定义的。

非常感谢您对此问题的任何帮助。


问题中有太多噪音了。您能否创建一个 StackBlitz? - SiddAjmera
1个回答

4

如果我理解正确,您想将一个新的生物体添加到人口对象中的生物体列表中。这需要使用一个行为主题。

在您的示例中,您可以执行以下操作。

addOrganismToPopulation(organism: Organism){
    this.currentPopulationSource
        .pipe(take(1))
        .subscribe((population: Population) => {
            this.currentPopulationSource.next(
                new Population([...population.getIndividuals(), organism]))
            )
        });
  }

那么我们在这里做什么呢?要将新的生物体添加到当前人口中,我们需要知道生物体的清单。因此,我们订阅保存人口的可观察对象。在订阅内部,我们创建了一个新的人口实例。在创建新实例时,我们创建了一个已知生物和新生物的数组。然后我们将新/更新的人口嵌套到流中。
请注意,我只取流的一个值,take(1)。这是因为当我们想计算新的生物清单时,我们只需要当前的人口。这也可以防止不必要的内存泄漏。 take操作符会在传递了一个事件后取消订阅流。
行为主题是否是您用例的最佳选择很难说,因为缺少最少信息。

1
谢谢,@Ruben!你理解的很正确。我也修复了我的Population构造函数中的一个错误(在上面编辑过)。 - Atticus29

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接