Axios İpuçları #4: localForage ile HTTP Yanıtlarını IndexedDB’de Önbelleklemek

Axios serisindeki bir önceki yazı: Axios İpuçları #3: LRU Cache ile HTTP Yanıtlarını Önbelleklemek

Daha önce, Axios istemcisiyle yapılan HTTP isteklerinin yanıtlarını istemci üzerinde önbelleklemeye dair bir yazı yazmıştım. O yazıda bahsettiğim yöntem, LRU cache algoritmasını kullanmakta ve HTTP yanıtlarını session storage’da saklamaktaydı.

Gerek session storage’da en fazla 5MB veri saklanabilmesi gerek de aktif tarayıcı sekmesi kapandığında session storage’daki verilerin sıfırlanması hasebiyle bu yöntem kısıtlı kullanım senaryolarında geçerliydi. SPA ve mobil uygulamalar gibi, istemci üzerinde render edilip (CSR) aynı oturumda hayatına devam eden uygulamalar için iyi bir çözüm sunarken sunucuda render edilen (SSR) ve/veya daha büyük boyutlu verilerin önbelleklenmesi gereken uygulamalarda yetersiz kalıyordu.

Bu yazıda buna alternatif olarak Axios ile IndexedDB üzerinde nasıl önbellekleme yapılacağından bahsedeceğim.

IndexedDB, istemci cihazlarında anahtar-değer (key-value pair) çiftleri formatında veri saklamaya olanak tanıyan bir web API’ı. Başka bir deyişle tarayıcı içerisinde tutulan bir NoSQL veritabanı aslında. Cookie, local storage, session storage gibi diğer çözümlerin aksine sabit bir veri saklama kapasitesi yok. İstemci diskindeki boş alan ve kullanılan tarayıcının yeteneklerine göre değişkenlik gösteriyor. İstisnalar olmakla birlikte kabaca istemci diskindeki boş alanın %50'si kadar bir depolama alanını IndexedDB kullanabiliyor. Bu alan dolduğunda ise en az kullanılandan başlanarak önbellekler birer birer siliniyor.

IndexedDB’nin tarayıcıda veri saklayabilen diğer yöntemlerden bir farkı da asenkron olarak çalışması. Örneğin local storage’a yapılan okuma ve yazma işlemleri senkrondur. Geliştirdiğimiz uygulama içerisinde local storage’a bir veri yazıyoruz diyelim. Bu veri yazma işlemi tamamlanana kadar uygulama geçici olarak bloklanır ve yazma işlemi tamamlandığında kaldığı yerden çalışmaya devam eder. Bunu o kadar hızlı bir şekilde yapar ki ne uygulamada bir aksama yaşanır ne de son kullanıcı duraklamayı fark eder.

localForage

Fakat IndexedDB büyük boyuttaki verileri bir veritabanı gibi yönettiğinden doğası gereği farklıdır. Veritabanı oluşturmak, veritabanına bağlanmak, veri yazmak, veri okumak gibi işlemler API’ın sağladığı interface’ler aracılığıyla asenkron olarak yapılır. Fakat bu da beraberinde implementasyon zorluklarını getirir. Bu nedenle MDN dâhil olmak üzere birçok kaynak, IndexedDB operasyonlarını daha pratik kütüphaneler aracılığıyla yapmayı önerir. İsminden anlaşılacağı gibi, IndexedDB’i local storage kolaylığında kullanmayı amaçlayan localForage, bu kütüphanelerden en yaygın olanı. Kullanılan tarayıcıların yeteneklerine göre muhtelif polyfill çözümlerini de içeriyor.

Sıra geldi Axios, IndexedDB ve localForage üçlüsünü birlikte kullanmaya. İlk olarak bağımlılıkları kuralım.

NPM ile bağımlıkların kurulması

Akabinde localforage için bir store oluşturalım. Bu store içerisinde localforage instance’ı yaratıyoruz. IndexedDB için kullanacağımız veritabanı adını ve driver bilgisini bu instance içerisinde tanımlıyoruz. Hemen yukarıda bahsettiğim polyfill çözümü burada karşımıza çıkıyor. Driver seçimi için birincil olarak IndexedDB’i, ikincil olarak ise local storage’ı belirtiyoruz. Kullanıcılar, IndexedDB’nin desteklenmediği bir tarayıcı kullanıyorlarsa uygulamanın akışı hiç bozulmadan veritabanı olarak local storage kullanılmaya başlanıyor. Son olarak HTTP yanıtlarının ne kadar süreyle önbellekleneceğini belirtip yarattığımız localforage instance’ının Axios ile eşleşmesini axios cache adapter marifetiyle sağlıyoruz.

localforage için store oluşturulması

Uygulama içerisinde, her tıklandığında GitHub’ın public API’larından istenilen kullanıcı bilgilerini getiren basit bir buton olduğunu varsayalım. Normal şartlarda GitHub API’ına yapacağımız HTTP isteğini, az önce oluşturduğumuz localforage instance’ı ile sarmalıyoruz. Bu sayede GitHub’a yapılacak HTTP istekleri için bir ara katman oluşturuyoruz. Böylece GitHub’a yapılacak tüm istekler ilk olarak localforage üzerinden geçecek ve isteğin yapılıp yapılmayacağına ve hangi yanıtın verileceğine localforage karar verecek.

http isteğinin localforage store’u ile sarmalanması

Uygulamayı çalıştıralım ve DevTools üzerinden izleyelim.

Butona tıklayıp DevTools’daki Network sekmesine baktığımızda HTTP isteğinin GitHub sunucularına yapıldığını ve karşılığında bir yanıt alındığını görüyoruz.

ilk http isteği

Akabinde Application sekmesindeki Storage > IndexedDB menüsüne baktığımızda githubCacheDB isimli bir veritabanı görüyoruz. Bu veritabanında anahtar (key) olarak seslendiğimiz API ucu, değer (value) olarak da bir obje görüyoruz. Obje içerisinde ise GitHub’dan bize dönen yanıt haricinde bir de zaman damgası (timestamp) var.

indexeddb içeriği

Tekrar uygulamadaki butona bastığımızda GitHub’dan alınan kullanıcı bilgilerinin yine ekrana yazıldığını ama GitHub sunucularına istemcimizden bir HTTP isteği çıkmadığını görüyoruz.

sonraki http istekleri

IndexedDB kaydı içerisindeki zaman damgası, GitHub sunucularından HTTP yanıtını aldığımız anın üstüne localforage store’unda tanımladığımız önbellekleme süresinin eklenmiş hâline karşılık geliyor. O zaman dolana kadar aynı API ucuna yapılacak tüm HTTP isteklerinin yanıtları IndexedDB’deki kayıttan verilecek ve GitHub sunucularına yeni bir istek yapılmayacak.

Sonuç olarak bir önceki önbellekleme yazısının finalini tekrar etmiş olayım. İlk bakışta çocuksu bir heyecanla her API ucunu önbelleklemek geliştirici olarak içimizden geçse de, hangi API ucunun neden ve ne kadar süreyle önbelleklenmesi gerektiğini ve önbelleklenmediğindeki maliyetini analiz etmeden bu işlere girişmek veri tutarsızlığı ve test zorlukları gibi birçok konu özelinde daha çok baş ağrıtabilir. Son olarak yazıda bahsi geçen basit uygulamayı da paylaşarak bitireyim.

--

--

Front-End Developer @Akbank — tugsanunlu.com

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store