我想实现一个请求的功能,它可以缓存结果。
要求是:
我找不到不使用类而在函数作用域内存储结果的方法。我尝试了下面的代码,但我发现 this.responses
实际上是一个全局变量,在 window.responses
. 有什么方法可以做到这一点?
function cachedRequest(url) {
if (!this.responses) this.responses = {} // This is actually a global variable at window.responses, cant use it
return new Promise((resolve, reject) => {
const cachedValue = this.responses[url]
if (cachedValue) {
console.log('returning cached result')
return resolve(cachedValue)
};
fetch(url).then(res => {
console.log('fetching and caching result')
this.responses[url] = res
return resolve(res)
})
})
}
const URL = "https://pokeapi.co/api/v2/pokemon/ditto/"
cachedRequest(URL).then((response) => {
console.log({response})
cachedRequest(URL)
})
你可以写一个 记事本 函数,它在一个闭包中跟踪哪些参数已经被使用。你可以将每个回调注入到 memo
函数来保持一个存储。
它还可以让你注入任何数量的参数,使你的代码非常灵活。
const memo = (callback) => {
const cache = new Map();
return (...args) => {
const selector = JSON.stringify(args);
if (cache.has(selector)) return cache.get(selector);
const value = callback(...args);
cache.set(selector, value);
return value;
};
};
const cachedRequest = memo(fetch);
const URL = "https://pokeapi.co/api/v2/pokemon/ditto/";
cachedRequest(URL).then((response) => {
console.log(response);
cachedRequest(URL);
});
你可以将你的请求函数包裹在另一个定义缓存对象的函数中。然后,返回的函数可以访问该对象。
function cachedRequest() {
const cache = {}
return function(url) { // returned function has access to `cache`
return new Promise((resolve, reject) => {
const cachedValue = cache[url]
if (cachedValue) {
console.log('returning cached result')
return resolve(cachedValue)
}
fetch(url).then(res => {
console.log('fetching and caching result')
cache[url] = res
return resolve(res)
})
})
}
}
const URL = 'https://pokeapi.co/api/v2/pokemon/ditto/'
const request = cachedRequest() // initialize the request caching function
request(URL).then(response => {
console.log({ response })
request(URL)
})
你可以绑定 cachedRequest
以自己为 this
函数内的上下文。
cachedRequest = cachedRequest.bind(cachedRequest);
承诺将保持相同的上下文,因为箭头函数不会创建一个新的上下文。
function cachedRequest(url) {
return new Promise((resolve, reject) => {
if (!this.responses) this.responses = {};
const cachedValue = this.responses[url]
console.log("function context => ", this.name);
console.log("this.responses => ", Object.keys(this.responses).length)
if (cachedValue) {
console.log('returning cached result')
return resolve(cachedValue)
};
fetch(url).then(res => {
console.log('fetching and caching result')
this.responses[url] = res
return resolve(res)
})
})
}
cachedRequest = cachedRequest.bind(cachedRequest);
const URL = "https://pokeapi.co/api/v2/pokemon/ditto/"
cachedRequest(URL).then((response) => {
cachedRequest(URL)
console.log("window.responses =>", window.responses != undefined);
})
你可以像这样使用模块模式。
const myApp = (() => {
let responses = {};
const cachedRequest = (url) => {
if (!this.responses) this.responses = {} // This is actually a global variable at window.responses, cant use it
return new Promise((resolve, reject) => {
const cachedValue = this.responses[url]
if (cachedValue) {
console.log('returning cached result')
return resolve(cachedValue)
};
fetch(url).then(res => {
console.log('fetching and caching result')
this.responses[url] = res
return resolve(res)
})
})
}
const init = (url) => {
cachedRequest(url);
};
return {
init
}
})();
const URL = "https://pokeapi.co/api/v2/pokemon/ditto/";
myApp.init(URL);
这样一来,只有init()是一个公共方法。其他的一切都无法访问。