如何实现在内部范围内缓存请求结果的函数。

问题描述 投票:0回答:4

我想实现一个请求的功能,它可以缓存结果。

要求是:

  • 不能使用 任何全局变量.
  • 结果应储存在 在函数的内部范围内 使用闭包。

我找不到不使用类而在函数作用域内存储结果的方法。我尝试了下面的代码,但我发现 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)
})
javascript caching promise scope closures
4个回答
2
投票

你可以写一个 记事本 函数,它在一个闭包中跟踪哪些参数已经被使用。你可以将每个回调注入到 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);
});

1
投票

你可以将你的请求函数包裹在另一个定义缓存对象的函数中。然后,返回的函数可以访问该对象。

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)
})

1
投票

你可以绑定 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);
})

0
投票

你可以像这样使用模块模式。

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()是一个公共方法。其他的一切都无法访问。

© www.soinside.com 2019 - 2024. All rights reserved.