Кэширование ответа getCapabilities с помощью Map

В своем JS-приложении я пытаюсь кэшировать ответы getCapabilities только для своих сервисов WMTS.

У меня есть эта функция, но когда функция вызывается дважды с одним и тем же baseUrl в объекте layer, запрос все равно отправляется дважды.

Однако похоже, что объект Map повторно инициализируется между вызовами. Я попытался добавить в функцию глобальный счетчик, но при каждом вызове счетчик оставался равным 0.

Я также готов попробовать другие решения для кэширования, кроме Map.

Вот мой код:

const cache = new Map()

export async function getCapabilities(layer, capabilitiesTimeout) {
  const libFetch = require('whatwg-fetch').fetch;
  const url = new URL(layer.views[0]?.baseUrl);
  const cachedRequestId = layer.views[0]?.baseUrl;

  if (!cache.get(cachedRequestId)) {
    const version = layer.views[0].serviceVersion;
    url.searchParams.append('SERVICE', layer.views[0].serviceType);
    url.searchParams.append('REQUEST', 'GetCapabilities');
    url.searchParams.append('VERSION', version);
  
    let response;
    let parsedResponse;
  
    try {
      response = await timeout(capabilitiesTimeout, fetch(getProxiedUrl(url)));
      const text = await response.text();
  
      if (layer.views[0].serviceType === TYPE_WMTS) {
        parsedResponse = parser.read(text);
        cache.set(cachedRequestId, parsedResponse);
      } else if (layer.views[0].serviceType === TYPE_WMS) {
        parsedResponse = parserWms.read(text);
      }
  
      return parsedResponse;
    } catch (e) {
      console.warn(
        `'GetCapabilities' timeout (${capabilitiesTimeout}ms) for layer "${
          layer?.title
        }"`,
        e
      );
    }
  }
  return cache.get(cachedRequestId)
}

«Я пытался добавить в функцию глобальный счетчик» — можете ли вы показать нам, как вы это сделали?

Bergi 22.02.2024 14:19

Кстати, что делает timeout? Лучше передать AbortSignal.timeout() в качестве опции сигнала на fetch

Bergi 22.02.2024 14:28
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Однако похоже, что объект Map повторно инициализируется между вызовами.

Нет, это не так. Скорее проблема в том, что…

когда функция вызывается дважды с одним и тем же baseUrl в объекте слоя, запрос все равно отправляется дважды

… потому что вы ничего не сохраняете в cache, пока не будет получен ответ. Таким образом, пока первый запрос еще выполняется, второй вызов getCapabilities увидит пустой кеш и выполнит собственный запрос.

Решением этой проблемы является кэширование самого обещания сразу при первом вызове.

export async function getCapabilities(layer, capabilitiesTimeout) {
  try {
    return await getCapabilitesCached(layer.views[0], AbortSignal.timeout(capabilitiesTimeout));
  } catch(err) {
    if (err.name == 'TimeoutError') {
      console.warn(
        `'GetCapabilities' timeout (${capabilitiesTimeout}ms) for layer "${
          layer?.title
        }"`,
        err
      );
    }
    throw err; // don't forget to rethrow!
  }
}

const cache = new Map();
function getCapabilitesCached(view, signal) {
  if (view.serviceType === TYPE_WMTS) {
    const cachedRequestId = view.baseUrl;
    if (!cache.has(cachedRequestId)) {
      cache.set(cachedRequestId, fetchCapabilities(view, signal));
      //                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      // no `await` before the `cache.set` call!
    }
    return cache.get(cachedRequestId);
  } else {
    return fetchCapabilities(view, signal);
  }
}

const { fetch } = require('whatwg-fetch');
async function fetchCapabilities(view, signal) {
  const url = new URL(view.baseUrl);
  url.searchParams.append('SERVICE', view.serviceType);
  url.searchParams.append('REQUEST', 'GetCapabilities');
  url.searchParams.append('VERSION', view.serviceVersion);
  
  const response = await fetch(getProxiedUrl(url), { signal });
  const text = await response.text();
  
  if (view.serviceType === TYPE_WMTS) {
    return parser.read(text);
  } else if (view.serviceType === TYPE_WMS) {
    return parserWms.read(text);
  }
}

Большое спасибо !! Я подумал, что это как-то связано с характером звонка async, но не мог понять, как это обойти.

cam_gis 22.02.2024 15:50

Другие вопросы по теме