


Meningkatkan Cache LRU dengan Kegigihan Data Boleh Dikonfigurasikan
Dec 26, 2024 pm 05:38 PMMembina asas panduan ini untuk mencipta cache dalam memori, kami akan meneruskannya dengan memperkenalkan kekekalan data boleh dikonfigurasikan. Dengan memanfaatkan corak Penyesuai dan Strategi, kami akan mereka bentuk sistem yang boleh diperluaskan yang memisahkan mekanisme storan daripada logik caching, membenarkan penyepaduan pangkalan data atau perkhidmatan yang lancar mengikut keperluan.
Visi: Menyahganding Seperti ORM
Matlamatnya adalah untuk menjadikan cache boleh dipanjangkan tanpa mengubah logik terasnya. Diilhamkan oleh sistem ORM, pendekatan kami melibatkan abstraksi API dikongsi. Ini membolehkan storan — seperti localStorage, IndexedDB atau pangkalan data jauh—berfungsi secara bergantian dengan perubahan kod yang minimum.
Kelas Asas Penyesuai Storan
Berikut ialah kelas abstrak yang mentakrifkan API untuk sebarang sistem kegigihan:
export abstract class StorageAdapter { abstract connect(): Promise<void>; abstract add(key: string, value: unknown): Promise<void>; abstract get(key: string): Promise<unknown | null>; abstract getAll(): Promise<Record<string, unknown>>; abstract delete(key: string): Promise<void>; abstract clear(): Promise<void>; }
Sebarang penyelesaian storan mesti memanjangkan kelas asas ini, memastikan konsistensi dalam interaksi. Sebagai contoh, berikut ialah pelaksanaan untuk IndexedDB:
Contoh: Penyesuai IndexedDB
Penyesuai ini melaksanakan antara muka StorageAdapter untuk mengekalkan data cache dalam gedung IndexedDB.
import { StorageAdapter } from './storage_adapter'; /** * IndexedDBAdapter is an implementation of the StorageAdapter * interface designed to provide a persistent storage mechanism * using IndexedDB. This adapter can be reused for other cache * implementations or extended for similar use cases, ensuring * flexibility and scalability. */ export class IndexedDBAdapter extends StorageAdapter { private readonly dbName: string; private readonly storeName: string; private db: IDBDatabase | null = null; /** * Initializes the adapter with the specified database and store * names. Defaults are provided to make it easy to set up without * additional configuration. */ constructor(dbName: string = 'cacheDB', storeName: string = 'cacheStore') { super(); this.dbName = dbName; this.storeName = storeName; } /** * Connects to the IndexedDB database and initializes it if * necessary. This asynchronous method ensures that the database * and object store are available before any other operations. * It uses the `onupgradeneeded` event to handle schema creation * or updates, making it a robust solution for versioning. */ async connect(): Promise<void> { return await new Promise((resolve, reject) => { const request = indexedDB.open(this.dbName, 1); request.onupgradeneeded = (event) => { const db = (event.target as IDBOpenDBRequest).result; if (!db.objectStoreNames.contains(this.storeName)) { db.createObjectStore(this.storeName, { keyPath: 'key' }); } }; request.onsuccess = (event) => { this.db = (event.target as IDBOpenDBRequest).result; resolve(); }; request.onerror = () => reject(request.error); }); } /** * Adds or updates a key-value pair in the store. This method is * asynchronous to ensure compatibility with the non-blocking * nature of IndexedDB and to prevent UI thread blocking. Using * the `put` method ensures idempotency: the operation will * insert or replace the entry. */ async add(key: string, value: unknown): Promise<void> { await this._withTransaction('readwrite', (store) => store.put({ key, value })); } /** * Retrieves the value associated with a key. If the key does not * exist, null is returned. This method is designed to integrate * seamlessly with caching mechanisms, enabling fast lookups. */ async get(key: string): Promise<unknown | null> { return await this._withTransaction('readonly', (store) => this._promisifyRequest(store.get(key)).then((result) => result ? (result as { key: string; value: unknown }).value : null ) ); } /** * Fetches all key-value pairs from the store. Returns an object * mapping keys to their values, making it suitable for bulk * operations or syncing with in-memory caches. */ async getAll(): Promise<Record<string, unknown>> { return await this._withTransaction('readonly', (store) => this._promisifyRequest(store.getAll()).then((results) => results.reduce((acc: Record<string, unknown>, item: { key: string; value: unknown }) => { acc[item.key] = item.value; return acc; }, {}) ) ); } /** * Deletes a key-value pair by its key. This method is crucial * for managing cache size and removing expired entries. The * `readwrite` mode is used to ensure proper deletion. */ async delete(key: string): Promise<void> { await this._withTransaction('readwrite', (store) => store.delete(key)); } /** * Clears all entries from the store. This method is ideal for * scenarios where the entire cache needs to be invalidated, such * as during application updates or environment resets. */ async clear(): Promise<void> { await this._withTransaction('readwrite', (store) => store.clear()); } /** * Handles transactions in a reusable way. Ensures the database * is connected and abstracts the transaction logic. By * centralizing transaction handling, this method reduces * boilerplate code and ensures consistency across all operations. */ private async _withTransaction<T>( mode: IDBTransactionMode, callback: (store: IDBObjectStore) => IDBRequest | Promise<T> ): Promise<T> { if (!this.db) throw new Error('IndexedDB is not connected'); const transaction = this.db.transaction([this.storeName], mode); const store = transaction.objectStore(this.storeName); const result = callback(store); return result instanceof IDBRequest ? await this._promisifyRequest(result) : await result; } /** * Converts IndexedDB request events into Promises, allowing for * cleaner and more modern asynchronous handling. This is * essential for making IndexedDB operations fit seamlessly into * the Promise-based architecture of JavaScript applications. */ private async _promisifyRequest<T>(request: IDBRequest): Promise<T> { return await new Promise((resolve, reject) => { request.onsuccess = () => resolve(request.result as T); request.onerror = () => reject(request.error); }); } }
Mengintegrasikan Penyesuai ke dalam Cache
Cache menerima StorageAdapter pilihan. Jika disediakan, ia memulakan sambungan pangkalan data, memuatkan data ke dalam ingatan dan memastikan cache serta storan sentiasa disegerakkan.
private constructor(capacity: number, storageAdapter?: StorageAdapter) { this.capacity = capacity; this.storageAdapter = storageAdapter; if (this.storageAdapter) { this.storageAdapter.connect().catch((error) => { throw new Error(error); }); this.storageAdapter.getAll().then((data) => { for (const key in data) { this.put(key, data[key] as T); } }).catch((error) => { throw new Error(error); }); } this.hash = new Map(); this.head = this.tail = undefined; this.hitCount = this.missCount = this.evictionCount = 0; }
Mengapa Corak Penyesuai dan Strategi?
Menggunakan corak Penyesuai:
- Decouples cache daripada mekanisme storan tertentu.
- Memastikan kebolehlanjutan untuk bahagian belakang storan baharu.
Menggabungkan dengan corak Strategi:
- Mendayakan pemilihan masa jalan lapisan kegigihan.
- Memudahkan ujian dengan mengejek penyesuai yang berbeza.
Amalan Reka Bentuk Utama
- API Abstrak: Mengekalkan logik cache agnostik butiran storan.
- Cache Singleton: Memastikan konsistensi keadaan dikongsi.
- Permulaan Async: Mengelakkan operasi menyekat semasa persediaan.
- Lazy Loading: Hanya memuatkan data berterusan apabila penyesuai storan disediakan.
Langkah Seterusnya
Reka bentuk ini teguh tetapi memberi ruang untuk penambahbaikan:
- Optimumkan logik penyegerakan untuk prestasi yang lebih baik.
- Percubaan dengan penyesuai tambahan seperti Redis atau SQLite.
Cubalah! ?
Jika anda ingin menguji cache dalam tindakan, ia tersedia sebagai pakej npm: adev-lru. Anda juga boleh menerokai kod sumber penuh pada GitHub: repositori adev-lru. Saya mengalu-alukan sebarang cadangan, maklum balas yang membina atau sumbangan untuk menjadikannya lebih baik! ?
Selamat pengekodan! ?
Atas ialah kandungan terperinci Meningkatkan Cache LRU dengan Kegigihan Data Boleh Dikonfigurasikan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Java dan JavaScript adalah bahasa pengaturcaraan yang berbeza, masing -masing sesuai untuk senario aplikasi yang berbeza. Java digunakan untuk pembangunan aplikasi perusahaan dan mudah alih yang besar, sementara JavaScript digunakan terutamanya untuk pembangunan laman web.

JavaScriptcommentsareessentialformaintaining,reading,andguidingcodeexecution.1)Single-linecommentsareusedforquickexplanations.2)Multi-linecommentsexplaincomplexlogicorprovidedetaileddocumentation.3)Inlinecommentsclarifyspecificpartsofcode.Bestpractic

Titik berikut harus diperhatikan apabila tarikh pemprosesan dan masa di JavaScript: 1. Terdapat banyak cara untuk membuat objek tarikh. Adalah disyorkan untuk menggunakan rentetan format ISO untuk memastikan keserasian; 2. Dapatkan dan tetapkan maklumat masa boleh diperoleh dan tetapkan kaedah, dan ambil perhatian bahawa bulan bermula dari 0; 3. Tarikh pemformatan secara manual memerlukan rentetan, dan perpustakaan pihak ketiga juga boleh digunakan; 4. Adalah disyorkan untuk menggunakan perpustakaan yang menyokong zon masa, seperti Luxon. Menguasai perkara -perkara utama ini secara berkesan dapat mengelakkan kesilapan yang sama.

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

JavaScriptispreferredforwebdevelopment, whersjavaisbetterforlarge-scalebackendsystemsandandroidapps.1) javascriptexcelsinceleatinginteractiveWebexperienceswithitsdynamicnatureanddommanipulation.2) javaoffersstrongyblectionandobjection

JavascripthassevenfundamentalDatypes: nombor, rentetan, boolean, undefined, null, objek, andsymbol.1) numberuseadouble-precisionformat, bergunaforwidevaluangesbutbecautiouswithfloating-pointarithmetic.2)

Penangkapan dan gelembung acara adalah dua peringkat penyebaran acara di Dom. Tangkap adalah dari lapisan atas ke elemen sasaran, dan gelembung adalah dari elemen sasaran ke lapisan atas. 1. Penangkapan acara dilaksanakan dengan menetapkan parameter useCapture addeventlistener kepada benar; 2. Bubble acara adalah tingkah laku lalai, useCapture ditetapkan kepada palsu atau ditinggalkan; 3. Penyebaran acara boleh digunakan untuk mencegah penyebaran acara; 4. Acara menggelegak menyokong delegasi acara untuk meningkatkan kecekapan pemprosesan kandungan dinamik; 5. Penangkapan boleh digunakan untuk memintas peristiwa terlebih dahulu, seperti pemprosesan pembalakan atau ralat. Memahami kedua -dua fasa ini membantu mengawal masa dan bagaimana JavaScript bertindak balas terhadap operasi pengguna.

Java dan JavaScript adalah bahasa pengaturcaraan yang berbeza. 1.Java adalah bahasa yang ditaip dan disusun secara statik, sesuai untuk aplikasi perusahaan dan sistem besar. 2. JavaScript adalah jenis dinamik dan bahasa yang ditafsirkan, terutamanya digunakan untuk interaksi web dan pembangunan front-end.
