首页 > 解决方案 > 来自可观察订阅的 Angular 7 奇怪行为

问题描述

我有一个代码来处理来自 observable 的一些数据,这个 observable 是通过 @Input 注释获取的,我订阅了我的 NgOnInit() 中的 observable,一切正常,但我需要添加代码以减少处理数据的时间,这是一个数组数组,我的数据如下所示:

[ ['id1', 对象, 对象], ['id2', 对象, 对象] ]

因此,为了减少处理时间,我创建了一个变量,该变量将保存 Observable 的先前后处理值,并将先前的数据与新数据进行比较,并仅更新更改的数据,我的代码如下所示:

 private dataSetHolder: Array<any> = [];

constructor() { }


ngOnInit() {
    this.dataSet$.subscribe(data => { //line 43
        console.log('inicio: ', this.dataSetHolder);
        data.forEach(array => {
            const dataNoId = Object.assign([], array);
            const id = array[0];
            dataNoId.shift();
            let pacote: Package = { eixo_x: [], eixo_y: [] };
            if (this.dataSetHolder.length === 0) {
                pacote = this.separaDados(dataNoId, id, pacote);
                this.loadData(pacote);
            } else {
                this.dataSetHolder.forEach(arrayHolder => {
                    if (id === arrayHolder[0]) {
                        if (array.length > arrayHolder.length) {
                            pacote = this.separaDados(dataNoId, id, pacote);
                            this.loadData(pacote);
                        }
                    }
                });
            }
        });
        this.dataSetHolder = data; //line 64
    });
}

执行第 64 行时,将数据的当前值传递给 this.dataSetHolder,当 observable 接收到新值时,再次执行第 43 行,执行第 43 行时更新 this.dataSetHolder 的值,那不应该发生,它应该只在第 64 行更新。

有人明白那里发生了什么吗?

插入图像描述

插入图像描述

插入图像描述

请注意,从最后一张图片到下一张我在调试时没有点击继续,我仍然在第 44 行

插入图像描述

我也尝试将第 64 行更改为此

            this.dataSetHolder = Object.assign([], data);

因为我认为它可能是由javascript引起的,因为当我这样做时 this.dataSetHolder = data; 它实际上并没有传递对象,只是传递了引用,但它仍然没有工作。

标签: angularrxjsobservablesubscribeangular-observable

解决方案


我的最终代码如下所示:

    ngOnInit() {
    this.dataSet$.subscribe(data => {
        data.forEach(array => {
            const dataNoId = Object.assign([], array);
            const id = array[0];
            dataNoId.shift();
            let pacote: Package = { eixo_x: [], eixo_y: [] };
            if (this.dataSetHolder.length === 0) {
                pacote = this.separaDados(dataNoId, id, pacote);
                this.loadData(pacote);
            } else {
                this.dataSetHolder.forEach(arrayHolder => {
                    if (id === arrayHolder[0]) {
                        const length = Object.keys(arrayHolder).length;
                        if (array.length > length) {
                            pacote = this.separaDados(dataNoId, id, pacote);
                            this.loadData(pacote);
                        }
                    }
                });
            }
        });
        this.dataSetHolder = [];
        data.forEach(dataItem => this.dataSetHolder.push({... dataItem}));
    });
}

感谢 bmtheo 的评论,我解决了问题,正如他解释的那样,即使使用 Object.assign() 复制数据也是不够的,因为我的数据是一个数组数组,当我使用 Object.assign() 时,我复制了我的数组的第一级,但第二级数组没有被复制,它们被引用,这就是为什么每次有新值可用时数据都会改变。

解决方案是清空我的数组,并将每个子数组复制到其中。除此之外,我还改变了获取arrayHolder长度的方式,因为它不再被解释为数组,它被视为一个对象,不会影响其余代码,所以我将此添加const length = Object.keys(arrayHolder).length;到我的代码中。


推荐阅读