【发布时间】:2016-10-21 14:43:24
【问题描述】:
我正在尝试创建一个满足以下要求的可观察流:
- 在订阅时从存储中加载数据
- 如果数据尚未过期,则返回存储值的可观察对象
- 如果数据已过期,则返回一个 HTTP 请求 observable,它使用刷新令牌获取新值 并存储它
- 如果在请求完成之前再次到达此代码,则返回相同的可观察请求
- 如果在上一个请求完成后或使用不同的刷新令牌到达此代码,则启动新请求
我知道关于如何执行第 (3) 步有很多不同的答案,但是当我尝试一起执行这些步骤时,我正在寻找有关我提出的解决方案是否是它可以是最简洁的(我对此表示怀疑!)。
这是一个演示我当前方法的示例:
var cachedRequestToken;
var cachedRequest;
function getOrUpdateValue() {
return loadFromStorage()
.flatMap(data => {
// data doesn't exist, shortcut out
if (!data || !data.refreshtoken)
return Rx.Observable.empty();
// data still valid, return the existing value
if (data.expires > new Date().getTime())
return Rx.Observable.return(data.value);
// if the refresh token is different or the previous request is
// complete, start a new request, otherwise return the cached request
if (!cachedRequest || cachedRequestToken !== data.refreshtoken) {
cachedRequestToken = data.refreshtoken;
var pretendHttpBody = {
value: Math.random(),
refreshToken: Math.random(),
expires: new Date().getTime() + (10 * 60 * 1000) // set by server, expires in ten minutes
};
cachedRequest = Rx.Observable.create(ob => {
// this would really be a http request that exchanges
// the one use refreshtoken for new data, then saves it
// to storage for later use before passing on the value
window.setTimeout(() => { // emulate slow response
saveToStorage(pretendHttpBody);
ob.next(pretendHttpBody.value);
ob.completed();
cachedRequest = null; // clear the request now we're complete
}, 2500);
});
}
return cachedRequest;
});
}
function loadFromStorage() {
return Rx.Observable.create(ob => {
var storedData = { // loading from storage goes here
value: 15, // wrapped in observable to delay loading until subscribed
refreshtoken: 63, // other process may have updated this between requests
expires: new Date().getTime() - (60 * 1000) // pretend to have already expired
};
ob.next(storedData);
ob.completed();
})
}
function saveToStorage(data) {
// save goes here
}
// first request
getOrUpdateValue().subscribe(function(v) { console.log('sub1: ' + v); });
// second request, can occur before or after first request finishes
window.setTimeout(
() => getOrUpdateValue().subscribe(function(v) { console.log('sub2: ' + v); }),
1500);
【问题讨论】:
-
您在第 3 阶段参数的第二部分中提到。除了
refreshtoken,还有其他参数吗?他们是从哪里传过来的?它们是如何比较的? -
唯一的参数是刷新令牌。我会更新问题以更清楚
-
谢谢。令牌是强制性的还是您只是使用它来确定是否需要发出新的后端请求?
-
令牌是强制性的。如果加载的数据为空或刷新令牌为空,则它会快捷方式并返回 observable.empty
-
没关系!我很欣赏细节。我已经更新以反映到期时间而不是到期标志
标签: javascript angular rxjs