Reputation: 3451
Here is my service:
import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/observable/of';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class CaseService {
private data:any;
private observable: Observable<any>;
constructor(private _http: Http) {}
public GetCase() {
const url = 'http://localhost:55130/api/case?caseId=123';
if (this.data) {
//after filtering an array of objects on a local variable
//in a controller, this.data is now modified
console.log(this.data);
return Observable.of(this.data);
} else if (this.observable) {
return this.observable;
} else {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.observable = this._http.get(url,{headers:headers})
.map(response => {
this.observable = null;
this.data = response.json();
return this.data;
}).share();
return this.observable;
}
}
}
In my home component, in the ngOnInit, I am doing the following:
ngOnInit() {
this._caseService.GetCase().subscribe(data => {
this.case = data;
//filter this.case.CaseContent array
//When I do this, it does return the correct object from the array
//but it also modifies the data variable on the shared service
//which is what I don't want
this.case.caseContent = this.case.CaseContent.filter(function(item){
return item.Route == '/home';
})[0];
});
}
Why when I modify the local variable in the home controller, it modifies the variable in the shared service. Basically what I am trying to do is when I go to the home page, I filter out the content for the home page and then when I access the contact page, I get the full object again, from the cache and filer out the content for the contact page, but when I go to the contact page, the CaseContent is now an object and not an array of objects.
Upvotes: 0
Views: 305
Reputation: 425
You're using same instance of 'data' variable. Returning reference type from method doesn't clone/copy that object, it just creates new pointer (that points to the same object in memory).
You can solve it by removing internal caching:
@Injectable()
export class CaseService {
constructor(private _http: Http) {}
public GetCase() {
const url = 'http://localhost:55130/api/case?caseId=123';
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this._http.get(url,{headers:headers})
.map(response => {
return response.json();
});
}
}
Or if you really want to cache observable and data, then you should clone that object on returning, smth like 'return Observable.of(DeepClone(this.data));'
Search in google how to deep clone objects in js, or implement a custom method.
In your case, would be best to cache just string json response and call 'JSON.parse()' on every access.
this.data = response.text();
return JSON.parse(this.data);
Upvotes: 2