我想以功能样式发出请求并将其缓存。
passes()
两个问题:
此代码惯用吗?
如何在保持关注点分离的同时提供逻辑以从结果生成缓存键?例如,我可能使用const req = (uri) =>
(console.log(`requesting: ${uri}`), Promise.resolve({ status: 200 }));
const cache = (fn) => (...args) =>
fn(...args).then((result) => { console.log('caching:', result) });
const cachedReq = cache(req);
cachedReq('example.com/foo');
来检索不同类型的资源,这些资源需要不同的逻辑来生成要在缓存中使用的密钥。我该如何向req
函数提供这种密钥生成逻辑?
编辑: 实际上,URI应该是关键(由于@epascarello)。我选择了一个糟糕的例子。但是我想问一个更一般的情况,即在保持适当的关注点分离的同时,需要“向下组合”提供逻辑。
答案 0 :(得分:0)
您几乎可以接近实现自己的目标,并且您朝着正确的方向前进,并且拥有构图概念。也许这段代码可以帮助您实现目标。
让我们像这样模拟您的req函数:
var req = (uri) => {
console.log("inside req", uri);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ status: 200 });
}, 3000);
});
}
然后将cacheFunc版本设置为:
var withCache = (promiseFunc) => {
const cache = {};
return (...args) => {
// suppose first param is uri
var uri = args[0];
return new Promise((resolve, reject) => {
if (cache.hasOwnProperty(uri)) {
return resolve(cache[uri]);
}
promiseFunc(...args).then((data) => {
cache[uri] = data;
resolve(data);
}).catch(reject);
});
}
}
如您所见,您需要将对象cache
创建到第一个函数中,所以这与Currying in JS有点相似,因此您需要包装请求(这是一个承诺)包装到另一个来自缓存版本的Promise中,因此在执行req函数之前,您需要验证是否有相同的uri键在缓存中存在某些响应(如果存在),因此请立即解决Promise,否则,请执行req函数接收响应缓存响应并解决缓存承诺版本。
因此您可以像这样使用它:
var cacheReq = withCache(req);
cacheReq('https://anywhere.com').then(console.log.bind(null, 'response')).catch(console.log.bind(null, 'error response'));
您会注意到,第一次您承诺等待3秒钟以解决请求,在第二次调用中,由于高速缓存,承诺将尽快解决承诺,如果尝试使用另一个uri,它将再次等待3秒钟,然后将缓存响应以便下次使用。
希望它可以为您提供帮助。
答案 1 :(得分:0)
您可以结合使用地图和Request constructor:
// I'll be using ramda for object equality, but any
// deepEquals checker should work.
const R = window.R;
const genRequest = ((cache, eqComparator) => {
return (url, fetchOpts={}) => {
const key = {url, fetchOpts};
const alreadyHave = [...cache.keys].find(x => eqComparator(x, key));
if (alreadyHave) return cache.get(alreadyHave);
const req = new Request(url, fetchOpts);
cache.set(key, req);
return req;
};
})(new Map(), R.equals);
const req = genRequest('http://www.google.com');
fetch(req)
.then(...)
.catch(...);
一些不错的属性不在此范围内
fetch
处理。