У меня есть приложение, которое выполняет много асинхронных вызовов fetch
, некоторые из которых идентичны.
У меня есть функция, которая устанавливает fetch
(скажем, fetchPlus
), создавая псевдо-уникальный идентификатор для запроса на основе аргументов.Таким образом, я могу сохранить результат в sessionStorage
и получить к нему доступ.
function fetchCacheStore(hash) {
const storeItem = 'fetch_' + hash;
return {
getCache: function () {
return JSON.parse(sessionStorage.getItem(storeItem));
},
setCache: function (data) {
sessionStorage.setItem(storeItem, JSON.stringify(data));
setTimeout(function () { sessionStorage.removeItem(storeItem); }, 25); // Clear the cache item shortly after
},
};
}
function fetchPlus() {
const stringHasher = function (s) { // Adapted from /4792022/generatsiya-hesha-iz-stroki-v-javascriptcomment94234739_7616484
for (var i = h = 0; i < s.length; i++) {
h = Math.imul(31, h) + s.charCodeAt(i) | 0;
}
return btoa(h);
}
let thisCallDetails = JSON.stringify(Array.prototype.slice.call(arguments).sort());
let fetchCallHash = stringHasher(thisCallDetails);
let fetchCache = fetchCacheStore(fetchCallHash);
let fetchCacheGet = fetchCache.getCache();
let promise;
if (fetchCacheGet === null) { // The data is not cached
promise = fetch(...arguments); // Create the fetch call
promise.then(data => {
data.close.json().then(content => {
fetchCache.setCache(content);
});
}); // Store the result in the cache
} else {
let dataHeaders = { "status": 200, "Content-Type": "application/json" };
promise = new Response(fetchCacheGet, dataHeaders); // Programatically create a Response
}
return promise;
}
Все работает хорошо, за исключением того факта, что когда данные существуют в sessionStorage
, я возвращаю объект JSON напрямую,а не Response
, поэтому в моем коде, когда я делаю вызов, например, так:
fetchPlus(url, params)
.then(response => response.json())
.then(data => …)
Я получаю сообщение об ошибке, сообщающее, что я не могу запустить json()
на response
.
Возможно, строка promise = new Response(fetchCacheGet, dataHeaders);
неверна, но я не уверен, как "обратить" данные в данные, выпавшие из исходного вызова fetch
.Может быть, я упускаю что-то очевидное.Или, может быть, это все неправильно.
Я открыт для предложений, но это приложение уже настроено, поэтому удаление всех .then(response => response.json())
из кодовой базы не вариант.
Также яЯ знаю, что мой код не лучший в своем классе, так что прости меня.Еще раз, откройте для предложений, пока это конструктивно.
Я хотел бы помочь сделать эту работу, если у кого-то есть несколько свободных минут.
ОБНОВЛЕНИЕ: Функциональный код
Благодаря ответу @ AuxTaxo ниже, я решил свою проблему.Для тех, кто заинтересован, вот обновленный код:
function fetchCacheStore(hash) {
const storeItem = 'fetch_' + hash;
return {
getCache: function () {
return sessionStorage.getItem(storeItem);
},
setCache: function (data) {
sessionStorage.setItem(storeItem, data);
setTimeout(function () { sessionStorage.removeItem(storeItem); }, 1000); // Clear the cache item after a short while
},
};
}
function fetchPlus() {
const stringHasher = function (s) { // Adapted from /4792022/generatsiya-hesha-iz-stroki-v-javascriptcomment94234739_7616484
for (var i = h = 0; i < s.length; i++) {
h = Math.imul(31, h) + s.charCodeAt(i) | 0;
}
return btoa(h);
}
let thisCallDetails = JSON.stringify(Array.prototype.slice.call(arguments).sort());
let fetchCallHash = stringHasher(thisCallDetails);
let fetchCache = fetchCacheStore(fetchCallHash);
let fetchCacheGet = fetchCache.getCache();
let promise;
if (fetchCacheGet === null) { // The data is not cached
promise = fetch(...arguments); // Create the fetch call
promise.then(data => {
data.clone().text().then(content => {
fetchCache.setCache(content) // Store the result in the cache
});
});
} else {
let dataHeaders = { "status": 200, headers: { "Content-Type": "application/json" } };
// Programatically create a Response object, which works as a Promise
promise = Promise.race([new Response(fetchCacheGet, dataHeaders)]);
}
return promise;
}
// Used as: `fetchPlus(url, params).then(response => response.json()).then(data => { /* … */ })`*