Angular 7 个来自可观察订阅的奇怪行为
Angular 7 Weird behavior from observable subscription
我有一个代码来处理一些来自可观察对象的数据,这个可观察对象是通过@Input 注释获取的,我在我的 NgOnInit() 中订阅了可观察对象,一切正常,但我需要添加减少数据处理时间的代码,这是一个数组数组,我的数据是这样的:
[['id1',对象,对象],['id2',对象,对象]]
所以为了减少处理时间,我创建了一个变量来保存 Observable 之前 post 处理过的值,我将之前的数据与新数据进行比较,并只更新发生变化的数据,我的代码如下所示:
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行执行时[=43的值=] 已更新,这不应该发生,它应该只在第 64 行更新。
有人知道那里发生了什么吗?
请注意,从最后一张图片到下一张我没有点击继续调试,我还在第 44 行
我也试过将第 64 行改成这个
this.dataSetHolder = Object.assign([], data);
因为我认为这可能是由javascript引起的,因为当我这样做时this.dataSetHolder = data;它实际上并没有传递对象,只是传递了引用,但它仍然不起作用。
我的最终代码如下所示:
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;
添加到我的代码中。
我有一个代码来处理一些来自可观察对象的数据,这个可观察对象是通过@Input 注释获取的,我在我的 NgOnInit() 中订阅了可观察对象,一切正常,但我需要添加减少数据处理时间的代码,这是一个数组数组,我的数据是这样的:
[['id1',对象,对象],['id2',对象,对象]]
所以为了减少处理时间,我创建了一个变量来保存 Observable 之前 post 处理过的值,我将之前的数据与新数据进行比较,并只更新发生变化的数据,我的代码如下所示:
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行执行时[=43的值=] 已更新,这不应该发生,它应该只在第 64 行更新。
有人知道那里发生了什么吗?
请注意,从最后一张图片到下一张我没有点击继续调试,我还在第 44 行
我也试过将第 64 行改成这个
this.dataSetHolder = Object.assign([], data);
因为我认为这可能是由javascript引起的,因为当我这样做时this.dataSetHolder = data;它实际上并没有传递对象,只是传递了引用,但它仍然不起作用。
我的最终代码如下所示:
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;
添加到我的代码中。