如何从 Observable 中过滤数组以获得浅拷贝而不是深拷贝?
How to filter an array from an Observable to get shallow copies instead of deep ones?
我的组件使用一些数据("ksr" 项目的数组,其中有一个 code
属性 可以被认为是一个 id)通过 xhr 加载到 Observable
dictionaries = {
ksr$: this.dictionaryService.fetchDictionaryByName('KSR'),
...
}
并且其中的一部分被过滤到另一个 Observable 中,如下所示:
formSuggestions = {
ksrCodes$: this.dictionaries.ksr$.pipe(map((plainKsrArray: Array<any>) =>
plainKsrArray.filter(ksrItem => ksrItem.levelName == "position"
)),
...
}
我预计在加载数据后,.formSuggestions
中的项目是 .dictionaries
中项目的浅表副本,但情况似乎并非如此。具体如下测试函数
async debugDictionariesAndSuggestions() {
let dictionary = await this.dictionaries.ksr$.toPromise();
let dItem = dictionary.find(item => item.code == '01.11.11.01.1.01.01-0001');
let suggestions = await this.formSuggestions.ksrCodes$.toPromise();
let sItem = suggestions.find(item => item.code == '01.11.11.01.1.01.01-0001');
console.log('found by code:', dItem, sItem, dItem == sItem ? 'same' : 'not same');
console.log(JSON.stringify(dItem) == JSON.stringify(sItem) ? 'they look the same' : 'they look different');
}
在 dictionary
和 suggestions
中找到项目,但报告它们不是同一事物(尽管 dItem
和 sItem
的所有嵌套属性都是同样,报告 "they look the same")。为什么会这样,我如何修改来自可观察对象的此类数据的处理方式(如何将 dictionaries.ksr$
过滤为 formSuggestions.ksrCodes$
),以便后者包含前者的项目(浅拷贝)?
就像@JBNizet 指出的那样,shareReplay
运算符是解决该问题的一种非常简单的方法。从 http 服务 observable 派生的 observable 的正常行为是 - 每个订阅(在我的例子中是承诺的:await this.dictionaries.ksr$.toPromise()
和 await this.formSuggestions.ksrCodes$.toPromise()
)触发一个新请求。但是如果我这样修改它:
dictionaries = {
ksr$: this.dictionaryService.fetchDictionaryByName('KSR').pipe(shareReplay()),
...
}
dictionaries.ksr$
可观察的和派生的只触发一个请求,结果值是共享的,这正是我一直在寻找的。
我的组件使用一些数据("ksr" 项目的数组,其中有一个 code
属性 可以被认为是一个 id)通过 xhr 加载到 Observable
dictionaries = {
ksr$: this.dictionaryService.fetchDictionaryByName('KSR'),
...
}
并且其中的一部分被过滤到另一个 Observable 中,如下所示:
formSuggestions = {
ksrCodes$: this.dictionaries.ksr$.pipe(map((plainKsrArray: Array<any>) =>
plainKsrArray.filter(ksrItem => ksrItem.levelName == "position"
)),
...
}
我预计在加载数据后,.formSuggestions
中的项目是 .dictionaries
中项目的浅表副本,但情况似乎并非如此。具体如下测试函数
async debugDictionariesAndSuggestions() {
let dictionary = await this.dictionaries.ksr$.toPromise();
let dItem = dictionary.find(item => item.code == '01.11.11.01.1.01.01-0001');
let suggestions = await this.formSuggestions.ksrCodes$.toPromise();
let sItem = suggestions.find(item => item.code == '01.11.11.01.1.01.01-0001');
console.log('found by code:', dItem, sItem, dItem == sItem ? 'same' : 'not same');
console.log(JSON.stringify(dItem) == JSON.stringify(sItem) ? 'they look the same' : 'they look different');
}
在 dictionary
和 suggestions
中找到项目,但报告它们不是同一事物(尽管 dItem
和 sItem
的所有嵌套属性都是同样,报告 "they look the same")。为什么会这样,我如何修改来自可观察对象的此类数据的处理方式(如何将 dictionaries.ksr$
过滤为 formSuggestions.ksrCodes$
),以便后者包含前者的项目(浅拷贝)?
就像@JBNizet 指出的那样,shareReplay
运算符是解决该问题的一种非常简单的方法。从 http 服务 observable 派生的 observable 的正常行为是 - 每个订阅(在我的例子中是承诺的:await this.dictionaries.ksr$.toPromise()
和 await this.formSuggestions.ksrCodes$.toPromise()
)触发一个新请求。但是如果我这样修改它:
dictionaries = {
ksr$: this.dictionaryService.fetchDictionaryByName('KSR').pipe(shareReplay()),
...
}
dictionaries.ksr$
可观察的和派生的只触发一个请求,结果值是共享的,这正是我一直在寻找的。