簡體   English   中英

如何防止可觀察的發射值發生變異

[英]How to prevent observable emitted value from being mutated

我訂閱了 observable 並將一個新元素取消移動到結果數組中,該數組會改變數據。 如果有人試圖改變數據而不是進行深度復制,如何通過拋出異常來防止服務級別的數據突變?

我有一個角度服務,可以根據國家/地區代碼從 API 獲取狀態列表。 它是一個單例服務,意味着在不同的模塊及其組件之間共享相同的實例。 我正在使用 ShareReplay() 緩存響應。 在我的組件中,我訂閱了 observable 並改變了結果(通過將新值移到數組中),緩存的數據被改變了。 現在我正在對結果進行深度復制,這很好,但是如果有人嘗試使用該服務並改變原始值而不是進行深度復制,我希望我的 observable 拋出異常。 我也嘗試讓服務返回可觀察的深拷貝,但那沒有用,我猜 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); }
        );
    }

您應該能夠對值(某處)使用Object.freeze

const test = [1,2,3,4];
Object.freeze(test);

test.unshift(0); // error will be thrown

無法添加屬性 5,對象不可擴展

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM