بهترین شیوه ها برای همگام سازی وضعیت برنامه بین IndexedDB یک کتابخانه مدیریت دولتی محبوب را بیاموزید.
هنگامی که کاربر برای اولین بار یک وب سایت یا برنامه را بارگذاری می کند، معمولاً مقدار زیادی کار در ساخت حالت اولیه برنامه که برای رندر UI استفاده می شود، انجام می شود. به عنوان مثال، گاهی اوقات برنامه نیاز به احراز هویت کاربر سمت مشتری دارد و سپس چندین درخواست API را قبل از اینکه تمام دادههایی را که برای نمایش در صفحه دارد داشته باشد، انجام دهد.
ذخیره وضعیت برنامه در IndexedDB می تواند یک راه عالی برای سرعت بخشیدن به زمان بارگذاری برای بازدیدهای مکرر باشد. سپس این برنامه میتواند با هر سرویس API در پسزمینه همگامسازی شود و با استفاده از استراتژی اعتبارسنجی مجدد ، رابط کاربری را با دادههای جدید بهروزرسانی کند.
یکی دیگر از کاربردهای خوب IndexedDB ذخیره محتوای تولید شده توسط کاربر است، یا به عنوان یک فروشگاه موقت قبل از آپلود در سرور یا به عنوان حافظه پنهان سمت مشتری از داده های راه دور - یا، البته، هر دو.
با این حال، هنگام استفاده از IndexedDB موارد مهم زیادی وجود دارد که باید در نظر بگیرید که ممکن است بلافاصله برای توسعه دهندگانی که به API ها تازه کار هستند آشکار نباشد. این مقاله به سوالات متداول پاسخ میدهد و برخی از مهمترین چیزهایی را که باید هنگام ماندگاری دادهها در IndexedDB در نظر داشت، مورد بحث قرار میدهد.
برنامه خود را قابل پیش بینی نگه دارید
بسیاری از پیچیدگیهای پیرامون IndexedDB از این واقعیت ناشی میشود که عوامل بسیاری وجود دارد که شما (توسعهدهنده) کنترلی روی آنها ندارید. این بخش بسیاری از مسائلی را که باید هنگام کار با IndexedDB در نظر داشته باشید بررسی می کند.
همه چیز را نمی توان در IndexedDB در همه سیستم عامل ها ذخیره کرد
اگر فایلهای بزرگ و تولید شده توسط کاربر مانند تصاویر یا ویدیوها را ذخیره میکنید، ممکن است سعی کنید آنها را بهعنوان اشیاء File
یا Blob
ذخیره کنید. این در برخی از پلتفرم ها کار می کند اما در برخی دیگر با شکست مواجه می شود. Safari در iOS، به ویژه، نمی تواند Blob
s را در IndexedDB ذخیره کند.
خوشبختانه تبدیل Blob
به ArrayBuffer
خیلی سخت نیست و بالعکس. ذخیره سازی ArrayBuffer
در IndexedDB به خوبی پشتیبانی می شود.
با این حال، به یاد داشته باشید که یک Blob
دارای نوع MIME است در حالی که یک ArrayBuffer
این گونه ندارد. برای اینکه تبدیل را به درستی انجام دهید، باید نوع را در کنار بافر ذخیره کنید.
برای تبدیل یک ArrayBuffer
به Blob
به سادگی از سازنده Blob
استفاده کنید.
function arrayBufferToBlob(buffer, type) {
return new Blob([buffer], { type: type });
}
جهت دیگر کمی بیشتر درگیر است و یک فرآیند ناهمزمان است. می توانید از یک شی FileReader
برای خواندن حباب به عنوان ArrayBuffer
استفاده کنید. هنگامی که خواندن به پایان رسید، یک رویداد loadend
در خواننده فعال می شود. شما می توانید این فرآیند را در یک Promise
مانند زیر بپیچید:
function blobToArrayBuffer(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener('loadend', () => {
resolve(reader.result);
});
reader.addEventListener('error', reject);
reader.readAsArrayBuffer(blob);
});
}
نوشتن در حافظه ممکن است ناموفق باشد
خطاها هنگام نوشتن در IndexedDB می تواند به دلایل مختلفی رخ دهد و در برخی موارد این دلایل خارج از کنترل شما به عنوان یک توسعه دهنده است. برای مثال، برخی از مرورگرها در حال حاضر اجازه نوشتن در IndexedDB را در حالت مرور خصوصی نمیدهند. همچنین این احتمال وجود دارد که کاربر در دستگاهی باشد که فضای دیسک تقریباً تمام شده است و مرورگر شما را از ذخیره کردن هر چیزی محدود می کند.
به همین دلیل، بسیار مهم است که همیشه مدیریت صحیح خطا را در کد IndexedDB خود پیاده سازی کنید. این همچنین به این معنی است که عموماً ایده خوبی است که وضعیت برنامه را در حافظه نگه دارید (علاوه بر ذخیره آن)، بنابراین هنگام اجرا در حالت مرور خصوصی یا زمانی که فضای ذخیره سازی در دسترس نیست (حتی اگر برخی از موارد دیگر، رابط کاربری خراب نشود) ویژگی های برنامه ای که به فضای ذخیره سازی نیاز دارند کار نمی کنند).
هر زمان که یک IDBDatabase
، IDBTransaction
یا شی IDBRequest
ایجاد می کنید، می توانید با افزودن یک کنترل کننده رویداد برای رویداد error
، خطاها را در عملیات IndexedDB دریافت کنید.
const request = db.open('example-db', 1);
request.addEventListener('error', (event) => {
console.log('Request error:', request.error);
};
داده های ذخیره شده ممکن است توسط کاربر اصلاح یا حذف شده باشد
برخلاف پایگاههای داده سمت سرور که میتوانید دسترسی غیرمجاز را محدود کنید، پایگاههای داده سمت سرویس گیرنده برای افزونههای مرورگر و ابزارهای توسعهدهنده قابل دسترسی هستند و کاربر میتواند آنها را پاک کند.
در حالی که ممکن است برای کاربران تغییر داده های ذخیره شده محلی خود غیر معمول باشد، پاک کردن آن برای کاربران بسیار رایج است. مهم است که برنامه شما بتواند هر دوی این موارد را بدون خطا انجام دهد.
داده های ذخیره شده ممکن است قدیمی باشند
مشابه بخش قبل، حتی اگر کاربر خودش دادهها را اصلاح نکرده باشد، ممکن است دادههایی که در ذخیرهسازی دارد توسط یک نسخه قدیمی کد شما نوشته شده باشد، احتمالاً نسخهای با اشکال در آن.
IndexedDB دارای پشتیبانی داخلی برای نسخه های طرحواره و ارتقاء از طریق روش IDBOpenDBRequest.onupgradeneeded()
است. با این حال، همچنان باید کد ارتقای خود را به گونهای بنویسید که بتواند با کاربر وارد شده از نسخه قبلی (از جمله نسخه دارای اشکال) کنترل کند.
تستهای واحد در اینجا میتوانند بسیار مفید باشند، زیرا اغلب امکان آزمایش دستی همه مسیرها و موارد ارتقاء ممکن نیست.
عملکرد برنامه خود را حفظ کنید
یکی از ویژگی های کلیدی IndexedDB API ناهمزمان آن است، اما اجازه ندهید که شما را فریب دهد و فکر کنید که در هنگام استفاده از آن نیازی به نگرانی در مورد عملکرد ندارید. تعدادی از موارد وجود دارد که استفاده نادرست همچنان می تواند نخ اصلی را مسدود کند، که می تواند منجر به jank و عدم پاسخگویی شود.
به عنوان یک قاعده کلی، خواندن و نوشتن در IndexedDB نباید بزرگتر از مقدار مورد نیاز برای داده های مورد دسترسی باشد.
در حالی که IndexedDB امکان ذخیره اشیاء بزرگ و تودرتو به عنوان یک رکورد را فراهم می کند (و مسلماً انجام این کار از دیدگاه توسعه دهنده بسیار راحت است)، باید از این عمل اجتناب شود. دلیل آن این است که وقتی IndexedDB یک شی را ذخیره میکند، ابتدا باید یک کلون ساختاریافته از آن شی ایجاد کند و فرآیند شبیهسازی ساختاریافته در رشته اصلی اتفاق میافتد. هر چه جسم بزرگتر باشد، زمان مسدود شدن بیشتر خواهد بود.
این امر در هنگام برنامه ریزی چگونگی تداوم وضعیت برنامه در IndexedDB چالش هایی را ایجاد می کند، زیرا اکثر کتابخانه های مدیریت دولتی محبوب (مانند Redux ) با مدیریت کل درخت حالت شما به عنوان یک شی جاوا اسکریپت کار می کنند.
در حالی که مدیریت وضعیت به این روش مزایای زیادی دارد (مثلاً استدلال و اشکال زدایی کد شما را آسان می کند)، و در حالی که صرفاً ذخیره کل درخت حالت به عنوان یک رکورد در IndexedDB ممکن است وسوسه انگیز و راحت باشد، انجام این کار پس از هر تغییر (حتی اگر throttle/debounced شود) منجر به مسدود شدن غیرضروری رشته اصلی میشود، احتمال خطاهای نوشتن را افزایش میدهد و در برخی موارد حتی باعث از کار افتادن تب مرورگر یا عدم پاسخگویی میشود.
به جای ذخیره کل درخت حالت در یک رکورد، باید آن را به رکوردهای جداگانه تقسیم کنید و فقط رکوردهایی را که واقعاً تغییر می کنند به روز کنید.
اگر آیتم های بزرگی مانند تصاویر، موسیقی یا ویدیو را در IndexedDB ذخیره کنید، همین امر صادق است. هر آیتم را با کلید خود به جای یک شی بزرگتر ذخیره کنید تا بتوانید داده های ساختاریافته را بدون پرداخت هزینه بازیابی فایل باینری بازیابی کنید.
مانند بسیاری از بهترین شیوه ها، این یک قانون همه یا هیچ نیست. در مواردی که شکستن یک شیء حالت و نوشتن مجموعه تغییرات حداقل امکان پذیر نیست، شکستن داده ها به درختان فرعی و فقط نوشتن آن ها همچنان بر نوشتن کل درخت حالت ترجیح داده می شود. بهبودهای کوچک بهتر از عدم پیشرفت است.
در نهایت، همیشه باید تأثیر عملکرد کدی را که مینویسید اندازهگیری کنید. در حالی که درست است که نوشتههای کوچک در IndexedDB بهتر از نوشتنهای بزرگ عمل میکنند، این تنها در صورتی مهم است که نوشتههای برنامه شما در IndexedDB واقعاً منجر به کارهای طولانی شود که رشته اصلی را مسدود کرده و تجربه کاربر را کاهش دهد. اندازه گیری بسیار مهم است تا بفهمید برای چه چیزی بهینه سازی می کنید.
نتیجه گیری
توسعهدهندگان میتوانند از مکانیسمهای ذخیرهسازی کلاینت مانند IndexedDB برای بهبود تجربه کاربری برنامهشان نه تنها با تداوم وضعیت در جلسات، بلکه با کاهش زمان بارگیری حالت اولیه در بازدیدهای مکرر، استفاده کنند.
در حالی که استفاده صحیح از IndexedDB می تواند تجربه کاربر را به طرز چشمگیری بهبود بخشد، استفاده نادرست از آن یا عدم رسیدگی به موارد خطا می تواند منجر به خراب شدن برنامه ها و کاربران ناراضی شود.
از آنجایی که ذخیره سازی مشتری شامل عوامل بسیاری خارج از کنترل شما می شود، بسیار مهم است که کد شما به خوبی آزمایش شده باشد و به درستی خطاها را کنترل کند، حتی آنهایی که ممکن است در ابتدا بعید به نظر برسد.