روش های مدرن ذخیره و بازیابی اطلاعات در مرورگر
ذخیره و بازیابی اطلاعات بخش جدا ناپذیری در نرم افزارهای امروزی است. در بسیاری از مواقع، ذخیره کردن اطلاعات و استفاده از آن ها در آینده امری ضروریست. چه این اطلاعات، اطلاعات کاربری در یک forum و چه لیست محصولات یک فروشگاه باشد.
یکی از روش های مرسوم ذخیره سازی اطلاعات در معماری کلاینت - سرور، ذخیره کردن آن ها در سرور است. معماری کلاینت-سرور به معماری گفته می شود که در آن کلاینت برای ذخیره و دریافت داده ها و انجام برخی عملیات ها با یک سرور در ارتباط باشد. سرور با دریافت اطلاعات از کلاینت، امکان ذخیره و بازیابی اطلاعات را خواهد داشت. این اطلاعات می توانند با روش های مختلفی در سرور ذخیره شوند (برای مثال درون یک دیتابیس یا ذخیره در یک فایل). اما در این حالت، کلاینت نیازی همیشگی به ارتباط با سرور خواهد داشت.
روش دیگری برای ذخیره سازی اطلاعات، ذخیره کردن آن ها در مرورگر است. ذخیره سازی اطلاعات در مرورگر با روش های مختلفی امکان پذیر است. یکی از این روش ها، استفاده از cookie است. این روش از ابتدای به وجود آمدن وب وجود داشته و تمامی مرورگرها از آن پشتیبانی می کنند. اما استفاده از cookie با چالش هایی همراه است. مهم ترین چالش ها عبارت اند از:
- فضای محدود: حداکثر حافظه ی قابل استفاده برای هر cookie تنها 4 کیلوبایت است. بنابراین برای ذخیره سازی داده های حجیم با مشکل روبرو خواهیم شد.
- ارسال در هر درخواست (request): cookie ها به همراه هر درخواستی که به سرور ارسال می شود، فرستاده خواهند شد.
- نیاز به ارتباط با سرور: برای دسترسی به cookie ها به ارتباط با سرور نیاز خواهیم داشت.
با وجود این چالش ها نیاز به استفاده از روش های جایگزینی برای ذخیره و بازیابی اطلاعات خواهیم داشت. خوش بختانه مرورگرها امکانات و روش های خوبی برای ذخیره سازی اطلاعات در اختیار توسعه دهندگان قرار داده اند. از جمله ی این روش ها می توان به موارد زیر اشاره کرد:
در ادامه ی این مقاله، به توضیح هر یک از موارد بالا خواهیم پرداخت.
WebSQL:
یکی از روش های ذخیره سازی اطلاعات در مرورگر، استفاده از WebSQL است. این روش برای ذخیره سازی، از زبان SQL استفاده می کند. به دلیل استفاده از SQL ، این روش برای بسیاری از توسعه دهندگانی که با SQL آشنا هستند، ملموس و ساده است. اما استفاده از WebSQL تقریبا منسوخ شده است و دیگر تمامی مرورگرها از آن پشتیبانی نمی کنند (مثل Mozilla Firefox). علت منسوخ شدن آن نبودن استاندارد منسجم در مرورگرها برای پشتیبانی از این API است. با توجه به عدم پشتیبانی مرورگرها از WebSQL ، استفاده کردن از آن توصیه نمی شود.
برای ساخت یک دیتابیس کافیست قطعه کد جاوااسکریپتی زیر به برنامه اضافه شود:
var db = openDatabase("mydatabase", "1.0", "a description for database", 4 * 1024 * 1024);
در دستور بالا از تابع openDatabase
برای ساخت دیتابیس (و دسترسی به دیتابیسی که قبلا ساختیم) استفاده شده است. آرگومان های این تابع به ترتیب، نام، نسخه ی دیتابیس، توضیح درباره ی دیتابیس و اندازه ی دیتابیس هستند.
برای اجرای یک کوئری به زبان SQL ، از دستور زیر استفاده می شود:
db.transaction(function (tx) {
tx.executeSql("CREATE TABLE cars (id unique,name);");
tx.executeSql("INSERT INTO cars(name) VALUES('BMW');");
var data = tx.executeSql("SELECT * FROM cars;", [], function (transaction, result) {
console.log(result.rows);
});
});
برای مشاهده ی دیتابیس ساخته شده، کافیست Developer Tools مرورگر خود را باز کرده، وارد زبانه Application شده و در قسمت WebSQL، دیتابیس ساخته شده را باز کنید.
LocalStorage:
روش دیگری برای ذخیره سازی اطلاعات در مرورگر، استفاده از LocalStorage است. در این روش، اطلاعات به صورت key:value
ذخیره می شوند. استفاده از این روش بسیار ساده است. برای ذخیره ی یک متغیر تنها کافیست از کد جاوااسکریپتی زیر در فایل html خود استفاده کنید:
localStorage.setItem("myKey", "myValue");
و برای بازیابی آن از دستور زیر استفاده کنید:
var data = localStorage.getItem("myKey");
در صورتی که داده ای با این key وجود نداشته باشد، این متد مقدار null باز می گرداند.
برای مشاهده ی localStorage
کافیست Developer tools مرورگر را باز کرده و در زبانه Application ، localStorage را باز کنید:
SessionStorage:
این روش، مانند روش قبلی از ذخیره سازی key:value
استفاده می کند. با این تفاوت که داده هایی که در sessionStorage
ذخیره می شوند، تنها در Session فعلی مرورگر در دسترسی خواهند بود و با بسته شدن مرورگر، این داده ها از دست خواهند رفت (قابل بیان است در روش های دیگر ذخیره سازی اطلاعات با بسته شدن مرورگر، این داده ها حفظ خواهند شد). برای ذخیره ی داده جدید همانند LocalStorage
، از متد setItem
استفاده می کنیم:
sessionStorage.setItem("myKey", "myValue");
و برای بازیابی داده با key مشخص شده از دستور زیر استفاده می کنیم:
var data = sessionStorage.getItem("myKey");
در صورتی که داده ای با این key وجود نداشته باشد، این متد مقدار null باز می گرداند.
برای مشاهده ی sessionStorage
کافیست Developer tools مرورگر را باز کرده و در زبانه Application ، sessionStorage
را باز کنید:
IndexedDB:
IndexedDB دیتابیسی برای ذخیره و بازیابی اطلاعات در سمت کلاینت است. این دیتابیس از امکاناتی مانند index ، transaction و Search پشتیبانی میکند و داده ها در این دیتابیس به صورت key:value
ذخیره می شوند. این روش ذخیره سازی سرعت بیشتری نسبت به localStorage
و sessiongStorage
دارد و از امکانات بیشتری نسبت به روش های قبلی برخوردار است.
از قابلیت های IndexedDB
می توان به جستجوی مناسب بین داده ها، امکان ذخیره داده های مختلف با key یکسان، استفاده از transaction برای جلوگیری از ذخیره داده در زمان بروز خطا و عدم محدودیت برای اندازه داده ها اشاره کرد.
برای ساخت و اتصال به یک دیتابیس در IndexedDB کافیست از کد جاوااسکریپتی زیر استفاده کنید:
var request = window.indexedDB.open("mydatabase", 1);
در کد بالا، از متد open برای اتصال به دیتابیس استفاده شده است. این متد دو آرگومان که اولی نام دیتابیس و دومی نسخه دیتابیس است را می پذیرد.
متغیر request
دو event
به نام های onsuccess
و onerror را داراست که بعد از باز شدن دیتابیس فراخوانی می شوند. در صورتی که خطایی هنگام اتصال به دیتابیس وجود داشته باشد، onerror و در صورت موفقیت آمیز بودن اتصال، onsuccess
اجرا خواهد شد:
request.onsuccess = function(event) {
// do stuff ...
}
request.onerror = function(event) {
// do stuff ...
}
همچنین event دیگری نیز وجود دارد که در صورت تغییر نسخه دیتابیس فراخوانی خواهد شد. این متد onupgradeneeded
نام دارد:
request.onupgradeneeded = function (event) {
// do stuff ...
event بالا، زمانی که نسخه دیتابیس در متد ()indexedDB.open
تغییر کند فراخوانی خواهد شد.
IndexedDB
به جای استفاده از table برای نگهداری داده ها، از مفهومی به نام Object Store
برای ذخیره سازی آن ها استفاده می کند. هر دیتابیس، می تواند به تعداد دلخواه Object Store داشته باشد. برای ساخت یک Object Store کافیست از کد زیر استفاده کنیم:
request.onupgradeneeded = function (event) {
var carsObjectStore = request.result.createObjectStore("cars", {autoIncrement: true});
};
در کد بالا، با استفاده از متد createObjectStor
یک Object Store در دیتابیس ایجاد کردیم. این متد دو آرگومان می پذیرد که اولی نام Object Store و دومی خصوصیات این Object Store است. برای اینکه key به صورت خودکار در Object Store ساخته شود از autoIncrement استفاده کردیم.
نکته: دقت کنید در هنگام استفاده از
indexedDB
برای دسترسی به دیتابیسی که درrequest
تعریف کردیم، از property ای به نامresult
استفاده شده است. دقت کنید که این property را در یکی از event هایonsuccess
و یاonupgradeneeded
استفاده می کنیم.
همچنین در IndexedDB
می توانیم index های مختلفی برای هر Object Store
بسازیم. برای ساخت یک index از کد زیر استفاده می شود (توجه داشته باشید این کار را در onupgradeneeded
انجام دادیم. بنابراین دقت کنید که برای اجرای این event باید نسخه دیتابیس تغییر کند. در غیر این صورت این event فراخوانی نخواهد شد):
request.onupgradeneeded = function (event) {
var carsObjectStore = request.result.createObjectStore("cars");
carsObjectStore.createIndex("name", "name");
carsObjectStore.createIndex("model", "model");
};
برای ذخیره داده در Object Store
از کد زیر استفاده می شود:
request.onsuccess = function (event) {
var carsObjectStore = request.result.transaction("cars", "readwrite").objectStore("cars");
var result = carsObjectStore.add({
name: "BMW",
model: "2012"
});
data.onsuccess = function (e) {
console.log(result);
};
};
در کد بالا، ابتدا با استفاده از متد objectStore
به Object Store
ساخته شده، دسترسی پیدا کرده و با استفاده از متد add
داده را در Object Store
ذخیره کردیم. برای دسترسی به ObjectStore
های ساخته شده در دیتابیس باید از متد transaction
استفاده کنیم. این متد دو آرگومان می پذیرد که اولی نام ObjectStore
و دومی mode مورد استفاده خواهد بود. برای خواندن و تغییر Object Store از حالت readwrite استفاده شده است.
برای بازیابی اطلاعات کافیست از کد زیر استفاده کنیم:
request.onsuccess = function (event) {
var carsObjectStore = request.result.transaction("cars", "readwrite").objectStore("cars");
var data = carsObjectStore.getAll();
data.onsuccess = function (e) {
console.log(data);
};
};
IndexedDB
در جستجو و بازیابی اطلاعات سرعت فوق العاده ای دارد و باعث افزایش سرعت اپلیکیشن خواهد شد. همچنین مرورگرهای مدرن از آن پشتیبانی می کنند. برای مشاهده ی IndexedDB
در Developer Tools
وارد زبانه ی Application شده و indexedDB
را انتخاب کنید.
نتیجه گیری:
همانطور که بررسی کردیم راه های مختلفی برای ذخیره و بازیابی اطلاعات در سمت کلاینت وجود دارد. نمیتوان گفت کدام یک از این راه ها بهترین راه است. ممکن است بسته به شرایط هر کدام مورد استفاده قرار گیرند. استفاده از localStorage
بسیار آسان است. sessionStorage
باعث ذخیره ی اطلاعات به صورت موقت خواهد شد و IndexedDB
امکان ذخیره و بازیابی اطلاعات زیاد را با سرعت بالا ارائه می دهد.
همچنین باید این نکته را در نظر گرفت که تمامی مرورگرها از این روش ها پشتیبانی نمی کنند. کافیست به درصد پشتیبانی مرورگرها (که از وب سایت google developers گرفته شده است) نگاهی بیندازیم:
API | Data Model | Persistence | Browser Support | Transactions |
WebSQL | structured | device | 77% | yes |
Local Storage | key/value | device | 93% | no |
Session Storage | key/value | session | 93% | no |
IndexedDB | hybrid | device | 83% | yes |
بنابراین هنگام استفاده از هر یک از این API ها، به این نکته دقت داشته باشید.
سخن پایانی:
در این مقاله روش های مختلف ذخیره ی اطلاعات در کلاینت معرفی و بررسی شد و نمونه کدهایی از هر یک ارائه شد. پیشنهاد می شود برای آشنایی بیشتر به لینک های زیر مراجعه کنید:
WebSQL: https://www.w3.org/TR/webdataba
LocalStorage: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
SessionStorage: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
IndexedDB: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
Browser Support: https://developers.google.com/web/fundamentals/instant-and-offline/web-storage
موفق باشید.