Как реализовать функцию, которая кэширует / запоминает результаты запросов во внутренней области видимости - PullRequest
0 голосов
/ 13 февраля 2020

Я пытаюсь реализовать функцию для отправки запросов, которая кэширует результаты.

Требования:

  • Невозможно использовать для любой глобальной переменной .
  • Результаты должны храниться во внутренней области функций с использованием замыкания.

Я не могу найти способ сохранить результат в области функций без использования класса , Я попробовал следующий код, но понял, что 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)
})

Ответы [ 4 ]

2 голосов
/ 14 февраля 2020

Вы можете написать функцию memoization , которая отслеживает внутри закрытия, какие аргументы уже используются. Вы можете внедрить каждый обратный вызов в функцию 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 голос
/ 13 февраля 2020

Вы можете обернуть вашу функцию запроса в другую функцию, которая определяет объект кэша. Затем возвращенная функция имеет доступ к этому объекту.

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 голос
/ 13 февраля 2020

Вы можете привязать 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 голосов
/ 13 февраля 2020

Вы можете использовать шаблон модуля следующим образом:

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 () будет методом publi c. Все остальное недоступно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...