【发布时间】:2019-05-25 12:28:06
【问题描述】:
我有两个 Observable,getUser 和 getUserAvatar。 它们都发出两个值 - 使用 BehaviorSubject 立即缓存,并在网络请求后真实。
现在代码是这样工作的:
1) 发送请求获取用户并立即发出缓存用户
2)缓存用户发出后,代码进入concatMap,第一次执行getUserAvatar
3)getUserAvatar 向服务器发送请求并立即发出缓存的userAvatar
4)一切都完成了,缓存的用户返回了缓存的头像
5) 一段时间后,真实用户返回,getUser 再次发出值
6) 在这一步,我想阻止第二次调用 concatMap,因为服务器请求已经在进行中,我只想返回 'USER LOADED。
sendGetRequest('/user/').pipe(
concatMap(() => {
// HERE, after user data loaded, I have url for his avatar
return sendGetRequest('/avatar/').pipe();
}),
map(() => {
return 'USER LOADED';
})
)
服务器请求代码
sendGetRequest(url: string, ignoreCache?: boolean): any {
let responseSubj = new Subject();
const cachedData = this.cache.getItemForUrl(url);
const cacheAllowed = cachedData && !ignoreCache;
if (cacheAllowed) {
responseSubj = new BehaviorSubject(cachedData);
}
const getFromServer = this.http.get(environment.API_SERVER_URL + url, this.addAuth()).pipe(
filter((res: any) => {
if (cacheAllowed && JSON.stringify(cachedData) === JSON.stringify(res)) {
responseSubj.complete();
return false;
}
this.cache.setItemForUrl(url, res).then(() => {
responseSubj.complete();
});
return true;
}),
catchError((error, caught) => {
console.log('ERROR FROM GET REQUEST', error);
return throwError(error);
})
);
return merge(responseSubj, getFromServer);
}
【问题讨论】:
-
请添加执行您描述的逻辑的代码
-
我添加了执行服务器请求的函数代码
-
你的第六点是什么。这不是很清楚。您正在调用 getUser() 但不是 getUserAvatar() 因为?还有,真实用户是什么意思?
-
您可以使用
forkJoin来代替请求和as of RxJS 6.5+ we can use a dictionary of sources,这在这里可能很方便learnrxjs.io/operators/combination/forkjoin.html -
你让这种方式太复杂了......你实际上甚至不需要科目......我会帮助你,但你的样本太混乱了。第一个代码部分与 getUser 和 getUserAvatar 调用之间是否有任何关系,第二部分与 sendGetRequest 调用之间是否存在任何关系?另外,您使用 concatMap 而不是 mergeMap 或 switchMap 是否有特定原因?