آموزش جاوا اسکریپت – جلسه ۱۳ – LocalStorage & SessionStorage & Cookie

در جلسه 12 از سری آموزشی جاوا اسکریپت تمام رویدادهای موس (mouse events) و property های آنها را معرفی کردیم و هریک را تا حد ممکن شرح دادیم. در این جلسه می خواهیم با دو آبجکت ذخیره سازی دیتا در مرورگر توسط جاوا اسکریپت آشنا شویم.
آبجکت های ذخیره سازی وب یا Web Storage به ما این امکان را می دهند که جفت های کلید/مقدار (key/value) را در مرورگر ذخیره کنیم. نکته جالبی که در مورد این آبجکت ها وجود دارد اینست کهsession-storage داده ها را تا زمان رفرش شدن صفحه وب نگهداری می کند و local-storage داده ها را بسته شدن پنجره مرورگر نگهداری کند.
مقایسه Cookie و LocalStorage و SessionStorage:
ابتدا نگاهی به شباهت و تفاوت سه روش ذخیره سازی دیتا در مرورگر کاربر بیاندازیم. به تصویر زیر توجه کنید:
به عنوان مثال مشاهده می کنید که فضای ذخیره سازی دیتا در کوکی فقط 4 کیلوبایت است در حالیکه این فضا برای لوکال استوریج 10 مگابایت و برای سشن استوریج 5 مگابایت می باشد. دلیل کم بودن حجم کوکی در مقایسه با دو روش دیگر اینست که cookie می تواند به سرور ارسال شود پس باید تا حد امکان حجم کمی داشته باشد تا سرعت ارسال request و دریافت response کاهش نیابد.
session storage فقط در تب جاری فعال است و اگر تب مرورگر بسته شود، سشن هم از بین خواهد رفت. اما کوکی و لوکال استوریج در تمام تب های مرورگر قابل دستیابی می باشد و با بستن تب پاک نمی شوند.
از طرف دیگر، cookie هم می توان در سمت سرور ذخیره شود و هم سمت کلاینت. اما دو روش دیگر یعنی localstorage و sessionstorage فقط از طرف کلاینت یعنی مرورگر کاربر قابل دسترسی می باشند.
مقایسه این سه روش را می توان از لحاظ تاریخ انقضا هم مورد بررسی قرار داد. زمان انقضای کوکی بصورت دستی تنظیم می شود (مثلا می توان انقضای آن را یکسال بعد تعریف کرد!) اما لوکال استوریج تاریخ انقضا ندارد بطور خودکار حذف نمی شود، مگر اینکه کاربر بصورت دستی در مرورگر خود آن را پاک کند یا برنامه نویس آن را در کد خود حذف کند. در مورد سشن استوریج همانطور که قبلا گفتیم با بستن تب مرورگر از بین خواهد رفت و در تب های دیگر و سایر مرورگرها قابل دستیابی نخواهد بود.
نحوه تعریف کوکی (Cookie):
برای تعریف کوکی در مرورگر کافیست دستور زیر را در کنسول مرورگر تعریف کنیم:
document.cookie = 'brand=Rahkarino'
در کد بالا، در مقابل دستور document.cookie مقدار موردنظر را می نویسیم. در این مثال، brand بعنوان key و Rahkarino بعنوان value تعریف شده است.
به منظور تعریف زمان انقضای کوکی، به شکل زیر عمل می کنیم:
let now = new Date(); let time = now.getTime(); time += 3600 * 1000; now.setTime(time); document.cookie = 'brand=Rahkarino-Academy; expires=' + now.toUTCString();
در کد فوق، گفتیم که کوکی brand در طی یکساعت آینده منقضی شود. اکنون اگر به تب Application و منوی Cookie مراجعه کنیم تاریخ انقضای کوکی brand آپدیت شده است:
در تصویر فوق مشاهده می کنید که کوکی brand در ساعت 16:52 تاریخ 22 ژانویه 2023 منقضی خواهد شد.
نکته: اگر کلید کوکی یکسان باشد، مقدار آن جایگزین قبلی می شود. در مثال فوق، کلید brand را مجددا تعریف کردیم و مقدار جدید یعنی Rahkarino-Academy جایگزین مقدار قبلی شده است.
تفاوت Cookie با Web Storage:
سوال اینجاست: در حال حاضر که ما Cookie داریم چرا باید از این آبجکت های ذخیره سازی استفاده کنیم؟
- بر خلاف کوکی، آبجکت های web storage با هر بار درخواست، به سرور ارسال نمی شود. به همین خاطر می توانیم مقدار داده های بیشتری را در آن ذخیره کنیم. بسیاری از مرورگرها امکان ذخیره سازی 2 مگابایت داده را به کاربران می دهند که این مقدار در تنظیمات مربوط به آن قابل تغییر است.
- برخلاف کوکی، آبجکت های لوکال استوریج و سشن استوریج در سمت سرور توسط هدرهای HTTP قابل تغییر و دستکاری نمی باشند.
- عملیات ذخیره سازی به دامین متصل است یعنی کلید/مقدار های ذخیره شده در مرورگر به دامین ارتباط دارند. حتی ساب دامین نیز نمی تواند به داده های دامین اصلی دسترسی داشته باشد.
لیست متدها و propertyهای وب استوریج:
هر دوی Local storage و Session storage متدها و property های یکسانی دارند:
- setItem(key, value) : برای ذخیره کلید/مقدار
- getItem(key) : برای دریافت مقدار توسط کلید
- removeItem(key) : برای حذف مقدار توسط کلید
- ()clear : برای حذف تمام مقادیر
- key(index) : برای دریافت کلید مربوط به ایندکس ارائه شده
- length : تعداد آیتم های ذخیره شده در وب استوریج
همانطور که مشاهده می کنید متدهای این دو آبجکت شبیه کالکشن Map می باشند (setItem/getItem/removeItem).
حالا وقت آنست که ببینیم Local Storage چگونه کار می کند.
آبجکت ذخیره سازی Local Storage:
ویژگی های اصلی لوکال استوریج:
بین تمام تب ها و پنجره های مرورگر از یک دامین یکسان مشترک است. داده های ذخیره شده منقضی نمی شوند. حتی اگر پنجره مرورگر بسته شود یا حتی سیستم ریست شود.
بعنوان مثال اگر کد زیر را در تب کنسول مرورگر خود اجرا کنید:
localStorage.setItem('test', 1);
و مرورگر را ببنید و بار دیگر باز کنید، در کنسول آن می توانید توسط کد زیر آیتم ذخیره شده بالا را دریافت کنید:
alert( localStorage.getItem('test') ); // 1
در بازیابی داده های ذخیره شده در مرورگر توسط local storage فقط کافیست تحت یک دامین عمل کنید. حتی در url های مختلف در یک دامین نیز می توان به آیتم های ذخیره شده دسترسی داشت.
همانطور که قبلا اشاره کردیم می توانیم در تب ها و پنجره های مختلف مرورگر نیز به آیتم های ذخیره شده دسترسی پیدا کنیم. به شرطی که دامین آنها یکسان باشد.
دسترسی به آیتم های ذخیره شده در local storage:
ما می توانیم مانند کار با آبجکت ها، به آیتم های localstorage دسترسی داشته باشیم:
// set key localStorage.test = 2; // get key alert( localStorage.test ); // 2 // remove key delete localStorage.test;
اما استفاده از روش فوق برای set و get کردن مقادیر در local storage توصیه نمی شود. زیرا:
از آنجائیکه key به دلخواه کاربر تعریف می شود، ممکن است نامی برای آن در نظر گرفته شود که در جاوا اسکریپت رزرو شده باشد، مانند length یا toString. در اینصورت با خطا مواجه خواهیم شد:
let key = 'length'; localStorage[key] = 5; // Error, can't assign length
پیمایش روی کلیدهای آبجکت Local storage:
تا اینجا یاد گرفتیم چگونه به مقدار یک آیتم توسط کلید آن دسترسی پیدا کنیم. اما اگر بخواهیم به تمام آیتم های ذخیره شده در local storage دسترسی داشته باشیم چه باید کرد؟
متاسفانه آبجکت های ذخیره سازی قابل iterable نمی باشند. یکی از روش های پیمایش و لوپ زدن روی آیتم های لوکال استوریج، رفتار کردن با آن بصورت یک آرایه است:
for(let i=0; i<localStorage.length; i++) { let key = localStorage.key(i); alert(`${key}: ${localStorage.getItem(key)}`); }
روش دیگر استفاده از ساختار for..in بصورت for key in localStorage می باشد.
اما اگر بصورت زیر پیمایش را انجام دهیم، آیتم هایی که موردنیاز ما نیست هم در خروجی خواهند آمد:
// bad try for(let key in localStorage) { alert(key); // shows getItem, setItem and other built-in stuff }
پیشنهاد می کنیم برای بهینه شدن این دستورات، باید از فیلتر hasOwnProperty استفاده کنید:
for(let key in localStorage) { if (!localStorage.hasOwnProperty(key)) { continue; // skip keys like "setItem", "getItem" etc } alert(`${key}: ${localStorage.getItem(key)}`); }
روش دیگر اینست که ابتدا بوسیله Object.keys کلیدهای آبجکت را استخراج کرده و سپس مقادیر آنها را در یک حلقه بدست آوریم:
let keys = Object.keys(localStorage); for(let key of keys) { alert(`${key}: ${localStorage.getItem(key)}`); }
نکته:
رشته بودن مقادیر key و value:
دقت کنید که نوع داده ای کلید/مقدار (key/value) باید رشته (string) باشد. اگر نوع دیگری برای آنها تعریف شود، مانند عدد یا آبجکت، بصورت اتوماتیک به رشته تبدیل خواهند شد.
sessionStorage.user = {name: "John"}; alert(sessionStorage.user); // [object Object]
همچنین می توان برای ذخیره سازی آبجکت از JSON استفاده کرد:
sessionStorage.user = JSON.stringify({name: "John"}); // sometime later let user = JSON.parse( sessionStorage.user ); alert( user.name ); // John
برای اهداف خطایابی می توان کل آبجکت ذخیره سازی را توسط stringify به رشته تبدیل کرد:
// added formatting options to JSON.stringify to make the object look nicer alert( JSON.stringify(localStorage, null, 2) );
آبجکت Session Storage:
سشن استوریج به مراتب کمتر از لوکال استوریج مورد استفاده قرار می گیرد. متدهای آن نیز با local storage یکسان است اما محدودیت بیشتری دارند. داده ای که در Session storage ذخیره می شود فقط در تب فعال جاری شناخته شده است. حتی اگر تب دیگری با همین آدرس باز کنیم، سشن تغییر می کند و یکسان نخواهد بود. اما داخل iframe های داخل یک تب یکسان خواهد بود و سشن متفاوت نخواهد بود.
نکته مهم: داده های ذخیره شده در session storage با ریلود صفحه از بین نمی روند. اما با بسته شدن تب یا پنجره مرورگر، از بین می روند.
کد زیر را در کنسول مرورگر اجرا کنید:
sessionStorage.setItem('test', 1);
اکنون صفحه را رفرش کنید. مشاهده می کنید که داده ها از بین نمی روند:
alert( sessionStorage.getItem('test') ); // after refresh: 1
اما اگر در تب دیگر آدرس صفحه فوق را مجددا باز کنید و دستور دوم را اجرا کنید خروجی null خواهد بود.
رویداد storage:
وقتی داده ای در local storage یا session storage تغییر می کند، رویداد storage بطور اتوماتیک با خاصیت های زیر فعالسازی می شود:
- key : کلیدی که تغییر کرده است را بر می گرداند (اگر clear() فراخوانی شود مقدار key برابر null خواهد بود)
- oldValue : مقدار قبلی را بر می گرداند. (اگر آیتم بتازگی اضافه شده باشد null خواهد بود)
- newValue : مقدار جدید را بر می گرداند. (اگر کلید حذف شده باشد null بر می گرداند)
- url : آدرس داکیومنتی که عملیات آپدیت در آن رخ داده است.
- storageArea : آبجکت localStorage یا sessionStorage را بر می گرداند.
نکته مهم: رویداد storage در تمام ویندوزهایی فعال می شود که داده ذخیره شده قابل دسترسی می باشد. در خود پنجره ای که داده در آن ذخیره شده قابل استفاده نیست.
بیایید با یک مثال قضیه را روشن کنیم:
فرض کنید دو پنجره مرورگر با یک آدرس دامین باز است. پس اگر داده موردنظر توسط آبجکت local storage در مرورگر ذخیره شود، بین دو پنجره مذکور یکسان و مشترک خواهد بود.
برای تست قضیه، کد زیر را در دو پنجره متفاوت اجرا کنید:
// triggers on updates made to the same storage from other documents window.onstorage = event => { // same as window.addEventListener('storage', () => { if (event.key != 'now') return; alert(event.key + ':' + event.newValue + " at " + event.url); }; localStorage.setItem('now', Date.now());
در این مثال event.url برابر آدرس داکیومنتی است که داده در آن تغییر کرده است و event.storageArea شامل آبجکت ذخیره سازی است. ما اگر داده را توسط local storage آپدیت کرده باشیم، مقدار storagArea برابر localStorage و اگر توسط session storage تغییر یافته باشد مقدارش برابر sessionStorage می باشد.
در جلسه 14 از آموزش های جاوا اسکریپت راهکارینو سراغ مبحث جذاب اجرای انیمیشن در جاوا اسکریپت خواهیم رفت…
دیدگاهتان را بنویسید