Om funksjonen
Formål
Ett felles, herdet mønster for "les cache, ellers hent friskt og lagre i cache" - brukt av enhver funksjon som slår opp et gratis, nøkkelfritt eksternt API og mellomlagrer svaret lokalt (SSB, Frankfurter, Norges Bank, hva koster strømmen.no, ...). Cache-lesing, fersk henting og cache-skriving feiler alle uavhengig og stille, slik at ett svakt ledd (f.eks. IndexedDB utilgjengelig) aldri kan bryte resten av siden.
Egner seg for
- Tjenestefunksjoner som kombinerer et IndexedDB- eller annet lagringsoppslag med et nettverkskall og en fast levetid (TTL) for cachen.
- Data som aldri endres (sett cacheLifetimeMs: Infinity) - som en historisk valutakurs - der cachen i praksis er en varig lagringsmekanisme, ikke bare et ytelsesoptimalisering.
Egner seg ikke for
- Rene lagringsoppslag uten noe "fetchFresh"-steg (f.eks. å lese brukervalg) - der holder et vanlig db.get() med egen try/catch.
- Situasjoner der stale/utløpt cache aldri skal brukes som fallback ved nettverksfeil - funksjonen prioriterer bevisst en utløpt cache fremfor den oppgitte fallback-verdien når fersk henting feiler.
Signatur(er)
fetchWithCache(options: object, options.readCache: () => Promise<{value: *, fetchedAt: number}|undefined|null>, options.writeCache?: (entry: {value: *, fetchedAt: number}) => Promise<void>, options.fetchFresh: () => Promise<*>, options.isValid?: (value: *) => boolean, options.cacheLifetimeMs?: number, options.fallback?: *) => Promise<*>
| Parameter | Type | Beskrivelse |
|---|---|---|
options | object | Se options.readCache/writeCache/fetchFresh/isValid/cacheLifetimeMs/fallback under. |
options.readCache | () => Promise<{value: *, fetchedAt: number}|undefined|null> | Leser en tidligere lagret {value, fetchedAt}-post, eller undefined/null hvis ingen finnes. Får aldri kaste videre til kalleren. |
options.writeCache (valgfri) | (entry: {value: *, fetchedAt: number}) => Promise<void> | Lagrer en ny {value, fetchedAt}-post. Utelates helt hvis ingenting skal caches. |
options.fetchFresh | () => Promise<*> | Henter en fersk verdi (typisk et nettverkskall). |
options.isValid (valgfri) | (value: *) => boolean | Avgjør om en verdi (fra cache eller nettverk) er brukbar. |
options.cacheLifetimeMs (valgfri) | number | Hvor lenge en cachet verdi regnes som fersk nok til å brukes uten ny henting. |
options.fallback (valgfri) | * | Verdien som returneres hvis både cache og fersk henting mangler/feiler. |
Returnerer: Den beste tilgjengelige verdien: fersk gyldig verdi > gyldig, ikke-utløpt cache > utløpt-men-gyldig cache (hvis fersk henting feilet) > fallback.
import {fetchWithCache} from "/designsystem/funksjoner/nettverk/fetch-with-cache/fetch-with-cache.js";
import {db} from "../shared/db.js";
const CACHE_ID = "valutaliste-cache";
const CACHE_LIFETIME_MS = 30 * 24 * 60 * 60 * 1000;
export async function getCurrencyList() {
return fetchWithCache({
readCache: () => db.get("innstillinger", CACHE_ID).then((entry) => entry && {value: entry.currencyCodes, fetchedAt: entry.hentetTidspunkt}),
writeCache: ({value, fetchedAt}) => db.put("innstillinger", {id: CACHE_ID, currencyCodes: value, hentetTidspunkt: fetchedAt}),
fetchFresh: async () => {
const response = await fetch("https://api.frankfurter.dev/v2/currencies");
if (!response.ok) throw new Error("Valutaliste-oppslag feilet");
const data = await response.json();
return data.map((currency) => currency.iso_code).sort();
},
isValid: (value) => Array.isArray(value) && value.length > 0,
cacheLifetimeMs: CACHE_LIFETIME_MS,
fallback: ["NOK", "EUR", "USD", "GBP", "SEK", "DKK"],
});
}
Tilgjengelighet
Ikke relevant: ren logikk uten DOM eller UI.
Referanser
Brukes av:
okonomi/js/services/valutaer.jsokonomi/js/services/valutakurser.jsokonomi/js/services/boligprisstatistikk.jsokonomi/js/services/forbrukstatistikk.jsokonomi/js/services/formuesstatistikk.jsokonomi/js/services/gjeldsstatistikk.jsokonomi/js/services/lonnsstatistikk.jsokonomi/js/services/strompris.jsokonomi/js/services/styringsrente.js
Avhengigheter: Ingen