angular - 如何比较两个冷 Observable 的源(而不是它们发出的潜在流)
问题描述
场景:我正在使用 publishReplay 来缓存和重播 Angular 应用程序中的某些 Http 请求(由于一些已经在 rxjs 中修复的错误,使用 publishReplay 而不是 shareReplay)。
我的问题是,如果我检测到 URL 参数更改,我想强制缓存的 observable 源更新自身并使用 publishReplay 创建一个新的缓存 observable。我想也许这可以通过询问/比较新提出的可观察对象与现有缓存的可观察对象的源来实现,但我没有成功实现这一点。
我在寻找什么: 一种询问可观察对象来源的方法,以便我可以将其与另一个可观察对象的来源进行比较,以查看它们是否相同(在本例中为 url),或者其他一些检测 Http Observable 上的 url 的方法随 publishReplay 改变。此外,我试图将这个逻辑抽象到一个缓存机制中,这样我就不必在整个应用程序中散布代码来检测参数是否发生变化。
这是一个非常幼稚的示例,说明我想做的事情不起作用,输入源参数是新的 Observable ,其中包含一个 http 请求的句柄,而 origSource 是以前的 observable 包含相同的(尽管可能使用 publishReplay 似乎不承认的不同 url 参数)。
// determine if key exists and source is un-modified (i.e params did not change)
protected isEntreeValid<T>(key: ICacheKeyConstantsModel, source: Observable<T>): boolean {
if (!this.has(key)) { return false; }
if (this.has(key)) {
let origSource = this.cache.registry.get(key).source; // observable previously cached used to resubscribe to later and returned cached publishReplay response, or can be tickled to make the original http request again effectively busting the cache.
console.log('source: ', source);
console.log('are they equal', source.source === origSource.source); //always returns false but assume need to check some inner value of observable anyways and do a fuzzy comparison.
if (source.source !== origSource.source) { return false; }
}
return true;
}
上述方法:上述方法中的输入“源”参数只是一个指向 http.get 方法的指针,并以键/值对方式存储在 Map 中:即 Map,以便我们可以集中编组它们的缓存状态和其他属性方式更容易。基本上就是在这里,如果“键”已经存在,我想评估“源”以查看 URL 上的参数是否更改,因此如果它们有我们可以破坏缓存,或者如果它们没有,我们将返回publishReplay 结果。
注意:在这种情况下,我不打算/不想连接到 Observable,我只对比较这些 Observable 的来源感兴趣,而不是它们将发出的潜在流。
更新:找到了我要找的东西,虽然不知道为什么它在那里是 WAAAY。有没有一种巧妙的迭代方式,似乎在结构上与 Observables 一致,而不是我在创建这些时所做的奇怪事情的产物。确实看起来很奇怪,这个非常基本的信息会在那里很远(注意 url 已经被混淆了,这个例子没有参数):
属性位置是: Observable.value.source.source.source.source.source
该位置的对象结构为:
{
value: HttpRequest
body: null
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, headers: Map(0)}
method: "GET"
params: HttpParams {updates: null, cloneFrom: null, encoder: HttpUrlEncodingCodec, map: Map(0)}
reportProgress: false
responseType: "json"
url: "https://my-dev-server.com/primary/HealthCareApp/Patients"
urlWithParams: "https://my-dev-server.com/primary/HealthCareApp/Patients"
}
问题:任何干净/可靠的方法来展平,或深入到最内部的 Observable 而不订阅?
更新 2:
现在我正在使用类似下面的方法来提取 innerObservable,可能有更好的方法,但这是我们目前正在使用的方法:
// retrieve inner meta-data from cold observable for interrogation without subscribing
private extractInnerObservable<T>(source: Observable<T>): Observable<T> {
let target = observableOf(source)['value'];
while (target['source']) {
target = target['source'];
}
return target;
}
结果方法:
结论:仍然可以肯定地探索其他选项,但是我已经多次更新了这个问题,以分享我现在所处的状态,至少现在它解决了原始问题(尽管肯定不是以最优雅的方式)。但是,如果其他人正在为类似的事情而苦苦挣扎,那么分享一些这种疯狂最终导致的结果是有价值的。
解决方案
我会争辩在这里颠倒你的逻辑。如果有一些参数通过你想要更改缓存的请求,然后使用操作符来做......
private paramSource = new Subject<string>(); // whatever type is appropriate
cached$ = this.paramSource.pipe(
distinctUntilChanged(), // could add some custom compare function in here
switchMap(param => this.makeRequest(param)),
shareReplay(1) // whatever you wana do for caching
);
// call this whenever you might've wanted to run the observable inspection
updateParam(param: string) {
this.paramSource.next(param);
}
如果这直接实现了您的目标,则不是积极的,因为我不太清楚您的目标是什么,但希望这很接近。
推荐阅读
- swift - Define URLError cancel reason is authentication challenge
- javascript - Why can't I show images inside my slider baguetteBox?
- ethereum - Solidity overriding function is missing "override" specifier
- python - Accessing nested list variable output using subprocess
- css - Make gap between tab and tab content in javafx bigger
- python - tf.Concat() does not result in concatenated tensor
- kubernetes - 使用 Kustomize 将环境变量添加到 Kubernetes StatefulSet
- c++ - How to pass a class function to another within the same class?
- php - Add Unique Index to Existing Laravel 8 Migration Table When Duplicates In Database Exist
- f# - 从会话状态中删除密钥