conflict-nuxt-4/app/composables/useCachedRequest.js
Baghi330 7892a7cefb 1
2026-02-14 10:41:53 +03:30

88 lines
2.6 KiB
JavaScript
Executable File

// composables/useCachedRequest.js
import { useApiCache } from "~/composables/useApiCache";
const tryParseJSON = (str) => {
if (typeof str !== "string") return str;
if (!str.trim()) return null;
try {
return JSON.parse(str);
} catch (e) {
return str; // اگر parse نشد، رشته را همون‌طور برگردون
}
};
export const useCachedRequest = () => {
const cache = useApiCache();
const { $http: httpService } = useNuxtApp();
// ساختن کلید ساده و یکتا برای هر request
const getRequestKey = (config = {}) => {
const method = (config.crud || "GET").toUpperCase();
const payloadNorm = tryParseJSON(config.payload) ?? null;
return `${method}:${config.url}:${JSON.stringify(payloadNorm)}`;
};
// درخواست با cache و dedupe
const fetchRequest = async (config = {}) => {
if (!config?.url) throw new Error("apiConfig.url is required");
const key = getRequestKey(config);
// پاک کردن cache منقضی شده
if (cache.hasData(key) && cache.isExpired(key)) cache.removeData(key);
// 1. اگر قبلاً داده موجود است → برگردان
if (cache.hasData(key)) return cache.getData(key);
// 2. اگر درخواست در حال اجراست → promise را await کن (dedupe)
const pending = cache.getPending(key);
if (pending) return await pending;
// 3. ایجاد request جدید
const promise = (async () => {
let response;
const method = (config.crud || "GET").toUpperCase();
if (method === "POST") {
const payload = tryParseJSON(config.payload) ?? {};
response = await httpService.postRequest(config.url, payload);
} else {
response = await httpService.getRequest(config.url);
}
const data = response?.data ?? response;
// ذخیره با TTL در صورت وجود
const ttl = config.ttlSeconds || 0;
if (ttl > 0) {
cache.saveDataWithTTL(key, data, ttl);
} else {
cache.saveData(key, data);
}
return data;
})();
cache.setPending(key, promise);
try {
return await promise;
} finally {
cache.clearPending(key);
}
};
// پاکسازی دستی cache برای logout یا تغییر داده‌ها
const invalidate = (configOrKey) => {
const key =
typeof configOrKey === "string"
? configOrKey
: getRequestKey(configOrKey || {});
cache.removeData(key);
};
const clearAll = () => cache.clearAllData();
return { fetchRequest, invalidate, clearAll };
};