В своем 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)
}
Кстати, что делает timeout? Лучше передать AbortSignal.timeout() в качестве опции сигнала на fetch



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Однако похоже, что объект
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, но не мог понять, как это обойти.
«Я пытался добавить в функцию глобальный счетчик» — можете ли вы показать нам, как вы это сделали?