Add stale cache for public data

This commit is contained in:
TerryM
2026-05-28 23:09:18 +08:00
parent 5ae9647465
commit 320739f91b
8 changed files with 263 additions and 83 deletions

View File

@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { getJSON, itemsOrEmpty, type Category } from "../../api";
import { getJSON, itemsOrEmpty, readJSONCache, type Category } from "../../api";
import { RecommendedCard } from "../../components/RecommendedCard";
import { SectionHeader } from "../../components/SectionHeader";
import { langQuery, useI18n } from "../../i18n";
@@ -16,23 +16,46 @@ export function OfficialRecommendationsPage() {
const [err, setErr] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
const langParam = encodeURIComponent(langQuery(lang));
const languageParam = encodeURIComponent(sourceLanguageQuery(lang));
const categoriesUrl = `/api/categories?lang=${langParam}`;
const recommendedUrl = `/api/posts/recommended?lang=${langParam}&language=${languageParam}&limit=100`;
const applyItems = (
categories: Category[],
recommended: { items: Post[] },
) => {
const cats = itemsOrEmpty(categories);
setItems(
itemsOrEmpty(recommended.items).map((post) =>
postToResource(post, lang, cats),
),
);
};
setErr(null);
const cachedCategories = readJSONCache<Category[]>(categoriesUrl);
const cachedRecommended = readJSONCache<{ items: Post[] }>(recommendedUrl);
const showedCached = !!(cachedCategories && cachedRecommended);
if (showedCached) applyItems(cachedCategories, cachedRecommended);
Promise.all([
getJSON<Category[]>(`/api/categories?lang=${langParam}`),
getJSON<{ items: Post[] }>(
`/api/posts/recommended?lang=${langParam}&language=${languageParam}&limit=100`,
),
getJSON<Category[]>(categoriesUrl),
getJSON<{ items: Post[] }>(recommendedUrl),
])
.then(([categories, recommended]) => {
const cats = itemsOrEmpty(categories);
setItems(
itemsOrEmpty(recommended.items).map((post) =>
postToResource(post, lang, cats),
),
);
if (cancelled) return;
applyItems(categories, recommended);
})
.catch((e) => setErr(String(e)));
.catch((e) => {
if (!cancelled && !showedCached) setErr(String(e));
});
return () => {
cancelled = true;
};
}, [lang]);
if (err) {