فصل پیوست ۲: ذخیره‌ی داده‌ها در localStorage

Storing Data in LocalStorage

Vue.JS 2 - فصل پیوست 2: ذخیره ی داده ها در localStorage - قسمت 126

در جلسه قبل منطق نسبتا ساده ای را برای logout کردن خودکار کاربران ایجاد کردیم تا پس از منقضی شدن توکن امنیتی، کاربر از حساب کاربری اش بیرون انداخته شود. در این قسمت می خواهیم این کار را برای login انجام بدهیم. مسئله اینجاست که login بودن کاربر در حال حاضر در vuex (مدیریت state) ذخیره می شود و vuex نیز چیزی جز جاوا اسکریپت نیست بنابراین مانند تمام کدهای جاوا اسکریپت دیگر، با refresh شدن صفحه از کار می افتد. با این حساب راه حل ما استفاده از چیزی است که با refresh مرورگر حذف نشود: localStorage. باید در همین ابتدا تاکید کنم که localStorage ربطی به Vue ندارد و یکی از API های ساده خود مرورگر است. بنابراین می توانیم به فایل store.js رفته و در قسمت signup بگوییم:

signup({ commit, dispatch }, authData) {
  axios
    .post("/accounts:signUp?key=AIzaSyDtirb936QLEAL9Hbkn1st5c3cF3U7_cFI", {
      email: authData.email,
      password: authData.password,
      returnSecureToken: true
    })
    .then(res => {
      console.log(res);
      commit('authUser', {
        token: res.data.idToken,
        userId: res.data.localId
      });
      localStorage.setItem('token', res.data.idToken);
      localStorage.setItem('expiresIn', res.data.expiresIn);
      dispatch('storeUser', authData);
      dispatch('setLogoutTimer', res.data.expiresIn);
    })
    .catch(error => console.log(error));
}

همانطور که مشاهده می کنید به راحتی به localStorage دسترسی داریم و می توانیم متد SetItem را روی آن صدا بزنیم. آرگومان اول setItem یک نام برای مقداری است که باید در مرورگر ذخیره شود بنابراین هر نامی را که دوست دارید به صورت یک رشته به آن بدهید (من Token را انتخاب کرده ام). مقدار دیگری که به آن نیاز داریم، expiresIn است و همانطور که در جلسه قبل گفتم 3600 ثانیه می باشد اما کد بالا برای ذخیره آن کاملا غلط است! من در نوشتن کد بالا برای expiresIn از یک خطای منطقی استفاده کرده ام. آیا می توانید آن را تشخیص دهید؟ مشکل اینجاست که expiresIn برابر با 3600 ثانیه است (در زمان نوشتن این مقاله - ممکن است گوگل در آینده آن را تغییر بدهد) بنابراین ما 3600 ثانیه را ذخیره می کنیم و این مقدار در مرورگر تغییر نخواهد کرد، بلکه هر زمان هم که بخواهیم آن را دریافت کنیم، همان مقدار 3600 را دریافت می کنیم. راه حل صحیح بدین صورت است که زمان انقضاء را بر اساس این 3600 ثانیه محاسبه کنیم:

signup({ commit, dispatch }, authData) {
  axios
    .post("/accounts:signUp?key=AIzaSyDtirb936QLEAL9Hbkn1st5c3cF3U7_cFI", {
      email: authData.email,
      password: authData.password,
      returnSecureToken: true
    })
    .then(res => {
      console.log(res);
      commit('authUser', {
        token: res.data.idToken,
        userId: res.data.localId
      });
      const now = new Date();
      const expirationDate = new Date(now.getTime() + res.data.expiresIn * 1000);
      localStorage.setItem('token', res.data.idToken);
      localStorage.setItem('expirationDate', expirationDate);
      dispatch('storeUser', authData);
      dispatch('setLogoutTimer', res.data.expiresIn);
    })
    .catch(error => console.log(error));
}

من در اینجا برای محاسبه تاریخ انقضا به شکل زیر عمل کرده ام:

  • در ابتدا با صدا زدن Date بدون آرگومان، تاریخ حال حاضر را دریافت کرده و درون ثابتی به نام now قرار می دهیم.
  • سپس now را به علاوه expiresIn (3600 ثانیه) کرده ام اما ما باید کل عبارت را به صورت میلی ثانیه حساب کنیم بنابراین تابع getTime را روی now صدا زده ام که زمان را به صورت میلی ثانیه برمی گرداند و از طرفی expiresIn را نیز در 1000 ضرب کرده ام تا آن هم میلی ثانیه شود. با این کار کل عبارت در واحد میلی ثانیه حساب خواهد شد. سپس با استفاده از Date معادل تاریخ این میلی ثانیه را گرفته ام. توجه کنید که Date تاریخ را برمی گرداند نه میلی ثانیه.
  • در نهایت به جای expiresIn از expirationDate به عنوان آرگومان دوم استفاده کرده ام تا در localStorage ذخیره شود.

از آنجایی که ممکن است کد expirationDate کمی گیج کننده باشد آن را به قسمت های مختلف تقسیم کرده و توضیح می دهم. ما در ابتدا باید زمان حال را به علاوه مدت زمان اعتبار توکن امنیتی کنیم تا زمان دقیق انقضای آن را به دست بیاوریم:

const expirationDate = now + res.data.expiresIn;

در حال حاضر مقداری که محاسبه می شود بر اساس میلی ثانیه نیست و باید آن را بر اساس میلی ثانیه محاسبه کنیم. چرا؟ به دلیل اینکه بعدا آن را به date پاس خواهیم داد:

const expirationDate = now.getTime() + res.data.expiresIn * 1000;

حالا مقدار expirationDate بر اساس میلی ثانیه است. در نهایت ما تاریخ را می خواهیم نه میلی ثانیه را چرا که میلی ثانیه عدد بسیار بزرگی است و کار با آن جالب نیست. بنابراین کل این عبارت را به Date می دهیم:

const expirationDate = new Date(now.getTime() + res.data.expiresIn * 1000);

ما می توانیم همین منطق را عینا کپی کرده و در اکشن login قرار بدهیم چرا که در هنگام login نیز باید توکن کاربر را در مرورگر ذخیره کنیم:

login({ commit, dispatch }, authData) {
  axios
    .post(
      "/accounts:signInWithPassword?key=AIzaSyDtirb936QLEAL9Hbkn1st5c3cF3U7_cFI",
      {
        email: authData.email,
        password: authData.password,
        returnSecureToken: true
      }
    )
    .then(res => {
      console.log(res);
      const now = new Date();
      const expirationDate = new Date(now.getTime() + res.data.expiresIn * 1000);
      localStorage.setItem('token', res.data.idToken);
      localStorage.setItem('expirationDate', expirationDate);
      commit('authUser', {
        token: res.data.idToken,
        userId: res.data.localId
      });
      dispatch('setLogoutTimer', res.data.expiresIn);
    })
    .catch(error => console.log(error));
}

با این کار کدها را ذخیره کرده و به مرورگر می رویم. به نظر شما کدها کار می کنند؟ برای بررسی این موضوع باید به صفحه login رفته و وارد حساب خود شوید. در آنجا dev tools مرورگر خود را باز کرده (معمولا کلید f12) و به سربرگ Application بروید. از آنجا روی LocalStorage کلیک کرده و URL برنامه خودمان را (http://localhost:8080/) انتخاب می کنیم. سپس در قسمت راست پنجره مقادیر خود را مشاهده می کنیم (البته یک مقدار دیگری هم داریم که متعلق به webpack است و به خاطر npm run dev در حال اجرا است بنابراین با آن کاری نداریم):

داده های ما با موفقیت در localStorage ذخیره شده اند
داده های ما با موفقیت در localStorage ذخیره شده اند

بنابراین کدهای ما با موفقیت اجرا می شوند. حالا باید کاری کنیم که هنگام بالا آمدن برنامه، این مقادیر دریافت شده و با استفاده از آن ها login خودکار صورت بگیرد. راه حل شما برای این کار چیست؟

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش رایگان Vue js از صفر تا صد توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.