angular2 也避免更新参考变量

angular2 avoid updating reference variable also

为什么angular2要更新一个变量的所有引用?

问题陈述: 我有一项服务 returns 在调用 getData 方法时可以观察到

@Injectable()
export class BuildingService {

constructor(private http: Http){       
  }

buildings$: Observable<Building[]>;

getData() : Observable<Building[]>{
     if (this.buildings$) {
        this.buildings$ = this.http.get('http://localhost:8080/buildings')
         .map(this.extractData)
         .publishReplay(1)
         .refCount();     
     }
     return this.buildings$;
  }

 private extractData(res: Response) {
    let body = res.json();
    return body;
} 
}

在组件中,我订阅了从 getData 方法返回的可观察对象并进行了一些过滤,它工作正常

export class Component1 implements onInit{

   constructor(private _buildingService: BuildingService) {}

   buildings: Building[] = [];

   ngOnInit() {
        this._buildingService.getData()
        .subscribe(buildings => {
            this.buildings = buildings;
            this.buildings.forEach((building, index){
                if (building.id === 0) {
                    this.buildings.splice(index, 1);
                }
            });
        });     
   }

getUnfilteredData() {
    this._buildingService.getData()
        .subscribe(buildings => {
            this.buildings = buildings;         
        });
   }
}

但即使我也调用 getUnfilteredData() 时,我也得到了之前过滤的数据。有人可以解释为什么会出现这种行为以及如何避免这种情况吗?

您正在使用 .publishReplay(1).refCount(); 为正在工作的多个订阅者缓存数据。但是在您的 ngOninit 中,您正在将原始数据引用带入 this.buildings 并将其拼接。所以你的缓存数据也会受到影响。

解决方案是在过滤之前将数组切片(制作副本)到 this.buildings

 ngOnInit() {
        this._buildingService.getData()
        .subscribe(buildings => {
            this.buildings = buildings.slice();//slice instead of taking reference
            this.buildings.forEach((building, index){
                if (building.id === 0) {
                    this.buildings.splice(index, 1);
                }
            });
        });     
   }

或者您可以这样做:

 ngOnInit() {
            this.buildings = [];
            this._buildingService.getData()
            .subscribe(buildings => {

                buildings.forEach((building){
                    if (building.id !== 0) {
                        this.buildings.push(building);
                    }
                });
            });     
       }