我正在订阅可观察的内容,并将一个新元素移入结果数组,该数组会变异数据。如果有人尝试变异数据而不是进行深层复制,如何通过引发异常来防止服务级别的数据变异?
我有一个角度服务,可以根据国家/地区代码从API获取状态列表。这是一个单例服务,意味着在不同的模块及其组件之间共享同一实例。我正在用ShareReplay()缓存响应。在我的组件中,我订阅了可观察的变量并更改了结果(通过将新值取消移位到数组),则缓存的数据发生了更改。现在,我正在对结果进行深层复制,这很好,但是如果有人尝试使用该服务并更改原始值而不是进行深层复制,我希望我的观察对象抛出异常。我还尝试使服务返回可观察对象的深层副本,但这没有用,猜测lodash不知道如何深层复制可观察对象,除非我放弃shareReplay(),在服务级别上实现自己的ReplaySubject并使next()方法返回发射值的深层副本?
服务
@Injectable()
export class StatesService {
private states$: Observable<State[]> = null;
constructor(private _http: HttpService) {}
getStatesFromCountry(countryCode3: string, freshData: boolean = false): Observable<State[]> {
let code = Object.keys(CountryEnum)
.filter((key: any) => isNaN(key))
.find(key => key === countryCode3.toUpperCase());
if(!code) return Observable.throw("Country Code was not recognized. Make sure it exists in CountryEnum.");
let url: string = `api/states?country=${countryCode3}`;
if (freshData) return this.getStates(url);
return this.states$ ? this.states$ : this.states$ = this.getStates(url).shareReplay(1);
}
private getStates(url: string): Observable<State[]> {
return this._http.get(url)
.map(response => response)
.catch(error => Observable.throw(<ApiError>JSON.parse(error)));
}
}
组件
private loadStates(): Subscription {
const usaStates$ = this._statesService.getStatesFromCountry(CountryEnum[CountryEnum.USA]);
const canStates$ = this._statesService.getStatesFromCountry(CountryEnum[CountryEnum.CAN]);
return Observable.forkJoin(usaStates$, canStates$).subscribe(
([usaStates, canStates]) => {
this.statesList = _.cloneDeep(usaStates.concat(canStates));
//Here if I unshift without doing deep copy first, other
//components that are using this shared service will now
//receive a mutated array of states
this.statesList.unshift(<State>{id: null, code: 'All'});
},
error => { ApiError.onError(error, this._notificationService, this._loaderService); }
);
}
答案 0 :(得分:1)
您应该可以在值(某处)上使用Object.freeze。
const test = [1,2,3,4];
Object.freeze(test);
test.unshift(0); // error will be thrown
无法添加属性5,对象不可扩展