想象一个消息流,每个消息流都具有关联的用户ID。对于收到的每条消息,获取相关的用户信息(可观察到“用户获取”)。这些用户获取的可观察对象将保持活动状态,并监视目标用户将来的任何更改。
问题:
我在哪里:
我无法确定现有的运算符或方法来防止出现可重复观察到的事物,因此我编写了类似于switchMap
的运算符。我不喜欢在实践中该如何完成?
如果我能解决1,我相信纠正清理和重用的解决方案是refCount()
。
答案 0 :(得分:1)
如果我正确理解了问题,则您有一个流发出id
-s并基于该流事件,另一个流从远程位置(服务器)接收一些与ID相关的数据。
我建议的解决方案是创建一种store
来保存缓存的数据,并在从id
流中接收到一条消息后对其进行检查,并返回来自新请求或响应的响应。缓存的数据。
/**
* callBack end mocks an http request
*/
let callBackEnd$ = id => {
customLog("___________________");
customLog("Calling the server for " + id);
customLog("___________________");
return of({ id: id, data: `Some data about ${id}` });
};
/**
* idStream$ mock the stream of id-s to be called trough http request
*/
let idStream$ = from([1, 2, 2, 3, 1, 5, 3, 4, 5]);
/**
* We use reqStore$ to cache the already retrieved data
*/
let reqStore$ = new BehaviorSubject([]);
/**
* 1. We subscribe to the message stream ( the stream that will tell us what to load )
*
* 2. With `latestFrom` we take the current store and check for any cached data, and return
* the cached data or the response of the new request
*
* 3. If the response of the `switchMap` doesn't exist in our store we add it.
*/
idStream$
.pipe(
tap(message => customLog(`Receiving command to retrieve : ${message}`)),
withLatestFrom(reqStore$),
switchMap(([e, store]) => {
let elementSaved = store.find(x => x.id === e);
return elementSaved ? of(elementSaved) : callBackEnd$(e);
}),
withLatestFrom(reqStore$),
tap(([response, store]) => {
if (!store.find(x => x.id === response.id)) {
reqStore$.next([...store, response]);
}
})
)
.subscribe(([currentResponse, currentStore]) => {
customLog("Receiving response for " + currentResponse.data);
});
这里是Codesandbox的现场演示,希望对您有所帮助:)