88 lines
2.6 KiB
JavaScript
Executable File
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 };
|
|
};
|