پشتیبانی مرورگر
مرورگرهای مدرن امروزی گاهی اوقات صفحات را به حالت تعلیق در می آورند یا در صورت محدود بودن منابع سیستم به طور کامل آنها را کنار می گذارند. در آینده، مرورگرها می خواهند این کار را فعالانه انجام دهند، بنابراین انرژی و حافظه کمتری مصرف می کنند. Page Lifecycle API قلابهای چرخه حیات را فراهم میکند تا صفحات شما بتوانند با خیال راحت این مداخلات مرورگر را بدون تأثیر بر تجربه کاربر انجام دهند. نگاهی به API بیندازید تا ببینید آیا باید این ویژگی ها را در برنامه خود پیاده سازی کنید یا خیر.
پس زمینه
چرخه عمر برنامه یک راه کلیدی برای مدیریت منابع سیستم عامل های مدرن است. در اندروید، iOS و نسخههای اخیر ویندوز، برنامهها را میتوان در هر زمانی که بخواهید توسط سیستم عامل راهاندازی و متوقف کرد. این به این پلتفرمها اجازه میدهد منابع را در جایی که به بهترین وجه برای کاربر مفید هستند، سادهسازی و تخصیص مجدد دهند.
در وب، از لحاظ تاریخی چنین چرخه حیاتی وجود نداشته است و برنامه ها را می توان به طور نامحدود زنده نگه داشت. با تعداد زیادی از صفحات وب در حال اجرا، منابع حیاتی سیستم مانند حافظه، CPU، باتری و شبکه می توانند بیش از حد اشتراک داشته باشند که منجر به تجربه بد کاربر نهایی می شود.
در حالی که پلتفرم وب مدتهاست که رویدادهایی مرتبط با وضعیتهای چرخه حیات دارد - مانند load
، unload
، و visibilitychange
- این رویدادها فقط به توسعهدهندگان اجازه میدهند تا به تغییرات وضعیت چرخه عمر آغاز شده توسط کاربر پاسخ دهند. برای اینکه وب به طور قابل اعتماد بر روی دستگاههای کم مصرف کار کند (و به طور کلی در همه پلتفرمها از منابع آگاهتر باشد)، مرورگرها به راهی برای بازیابی فعال و تخصیص مجدد منابع سیستم نیاز دارند.
در واقع، امروزه مرورگرها اقدامات فعالی را برای حفظ منابع برای صفحات در برگههای پسزمینه انجام میدهند، و بسیاری از مرورگرها (مخصوصا کروم) مایلند کارهای بیشتری از این کار انجام دهند - تا ردپای کلی منابع خود را کاهش دهند.
مشکل این است که توسعه دهندگان راهی برای آماده شدن برای این نوع مداخلات آغاز شده توسط سیستم ندارند یا حتی می دانند که آنها در حال وقوع هستند. این بدان معناست که مرورگرها باید محافظه کار باشند یا در خطر شکستن صفحات وب هستند.
Page Lifecycle API سعی می کند این مشکل را با استفاده از موارد زیر حل کند:
- معرفی و استانداردسازی مفهوم حالت های چرخه حیات در وب.
- تعریف حالتهای جدید و شروعشده توسط سیستم که به مرورگرها اجازه میدهد منابعی را که میتوانند توسط برگههای مخفی یا غیرفعال مصرف میشوند، محدود کنند.
- ایجاد APIها و رویدادهای جدید که به توسعه دهندگان وب اجازه می دهد به انتقال به و از این حالت های جدید شروع شده توسط سیستم پاسخ دهند.
این راه حل قابلیت پیش بینی نیاز توسعه دهندگان وب را برای ساخت برنامه های کاربردی مقاوم در برابر مداخلات سیستمی را فراهم می کند و به مرورگرها اجازه می دهد تا منابع سیستم را با شدت بیشتری بهینه کنند و در نهایت به نفع همه کاربران وب باشد.
بقیه این پست ویژگی های جدید چرخه حیات صفحه را معرفی می کند و چگونگی ارتباط آنها با تمام وضعیت ها و رویدادهای پلت فرم وب موجود را بررسی می کند. همچنین توصیهها و بهترین روشها را برای انواع کارهایی که توسعهدهندگان باید (و نباید) در هر ایالت انجام دهند، ارائه میدهد.
مروری بر وضعیت ها و رویدادهای چرخه عمر صفحه
همه حالتهای چرخه عمر صفحه گسسته و متقابلاً انحصاری هستند، به این معنی که یک صفحه در یک زمان فقط میتواند در یک حالت باشد. و اکثر تغییرات در حالت چرخه عمر صفحه عموماً از طریق رویدادهای DOM قابل مشاهده است (به توصیه های توسعه دهنده برای هر حالت برای موارد استثنا مراجعه کنید).
شاید سادهترین راه برای توضیح حالتهای چرخه عمر صفحه - و همچنین رویدادهایی که سیگنال انتقال بین آنها را نشان میدهند - با یک نمودار باشد:
ایالات
جدول زیر هر حالت را به تفصیل توضیح می دهد. همچنین حالتهای احتمالی را که میتوانند قبل و بعد از آن بیایند و همچنین رویدادهایی که توسعهدهندگان میتوانند برای مشاهده تغییرات استفاده کنند، فهرست میکند.
ایالت | توضیحات |
---|---|
فعال | اگر صفحه قابل مشاهده باشد و فوکوس ورودی داشته باشد در حالت فعال است. حالات احتمالی قبلی: |
منفعل | اگر صفحه ای قابل مشاهده باشد و فوکوس ورودی نداشته باشد در حالت غیرفعال است. حالات احتمالی قبلی: حالات بعدی احتمالی: |
پنهان شده است | اگر صفحه ای قابل مشاهده نباشد (و ثابت، دور انداخته یا خاتمه نیافته باشد) در حالت پنهان است. حالات احتمالی قبلی: حالات بعدی احتمالی: |
منجمد | در حالت یخ زده ، مرورگر اجرای وظایف قابل انجماد را در صف های وظایف صفحه تا زمانی که صفحه از حالت یخ خارج شود، به حالت تعلیق در می آورد. این بدان معناست که مواردی مانند تایمرهای جاوا اسکریپت و واکشی تماس های برگشتی اجرا نمی شوند. کارهایی که از قبل در حال اجرا هستند می توانند به پایان برسند (مهمتر از همه، مرورگرها صفحات را به عنوان راهی برای حفظ مصرف CPU/باتری/داده مسدود می کنند. آنها همچنین این کار را به عنوان راهی برای فعال کردن ناوبری سریعتر به عقب و جلو انجام می دهند - اجتناب از نیاز به بارگذاری مجدد کامل صفحه. حالات احتمالی قبلی: حالات بعدی احتمالی: |
خاتمه یافت | یک صفحه پس از شروع بارگیری و پاک شدن از حافظه توسط مرورگر در حالت پایان قرار می گیرد. هیچ کار جدیدی نمی تواند در این حالت شروع شود و کارهای در حال انجام ممکن است در صورت طولانی شدن طولانی مدت از بین بروند. حالات احتمالی قبلی: حالات بعدی احتمالی: |
دور انداخته شد | هنگامی که یک صفحه توسط مرورگر به منظور حفظ منابع بارگیری می شود، در حالت رد شده است. هیچ کار، فراخوانی رویداد یا جاوا اسکریپتی از هر نوعی نمی تواند در این حالت اجرا شود، زیرا رد کردن معمولاً تحت محدودیت منابع رخ می دهد، جایی که شروع فرآیندهای جدید غیرممکن است. در حالت حذف ، خود برگه (شامل عنوان برگه و فاویکون) معمولاً برای کاربر قابل مشاهده است حتی اگر صفحه از بین رفته باشد. حالات احتمالی قبلی: حالات بعدی احتمالی: |
رویدادها
مرورگرها رویدادهای زیادی را ارسال می کنند، اما تنها بخش کوچکی از آنها تغییر احتمالی در وضعیت چرخه عمر صفحه را نشان می دهد. جدول زیر تمام رویدادهایی را که به چرخه حیات مربوط میشوند را نشان میدهد و فهرستی از حالتهایی که ممکن است به و از چه حالتهایی منتقل شوند را نشان میدهد.
نام | جزئیات |
---|---|
focus | یک عنصر DOM فوکوس دریافت کرده است. توجه: یک رویداد حالات احتمالی قبلی: حالات فعلی احتمالی: |
blur | یک عنصر DOM تمرکز خود را از دست داده است. توجه: یک رویداد حالات احتمالی قبلی: حالات فعلی احتمالی: |
visibilitychange | مقدار حالات احتمالی قبلی: حالات فعلی احتمالی: |
freeze * | صفحه به تازگی مسدود شده است. هر کار قابل انجماد در صف های کار صفحه شروع نمی شود. حالات احتمالی قبلی: حالات فعلی احتمالی: |
resume * | مرورگر یک صفحه ثابت را از سر گرفته است. حالات احتمالی قبلی: حالات فعلی احتمالی: |
pageshow | یک ورودی سابقه جلسه در حال عبور است. این میتواند یک بارگذاری صفحه کاملاً جدید باشد یا صفحهای که از کش عقب/ جلو گرفته شده است. اگر صفحه از حافظه پنهان عقب/ جلو گرفته شده باشد، ویژگی حالات احتمالی قبلی: حالات فعلی احتمالی: |
pagehide | یک ورودی سابقه جلسه از آن در حال عبور است. اگر کاربر در حال پیمایش به صفحه دیگری باشد و مرورگر بتواند صفحه فعلی را به حافظه پنهان عقب/ جلو اضافه کند تا بعداً دوباره از آن استفاده شود، ویژگی حالات احتمالی قبلی: حالات فعلی احتمالی: |
beforeunload | پنجره، سند و منابع آن در شرف تخلیه هستند. سند هنوز قابل مشاهده است و رویداد هنوز در این مرحله قابل لغو است. مهم: رویداد حالات احتمالی قبلی: حالات فعلی احتمالی: |
unload | صفحه در حال تخلیه است. هشدار: استفاده از رویداد حالات احتمالی قبلی: حالات فعلی احتمالی: |
* یک رویداد جدید را نشان می دهد که توسط صفحه Lifecycle API تعریف شده است
ویژگی های جدید اضافه شده در کروم 68
نمودار قبلی دو حالت را نشان میدهد که به جای شروع توسط کاربر، توسط سیستم راهاندازی شدهاند: منجمد و دور انداخته شده . همانطور که قبلاً ذکر شد، امروزه مرورگرها گاهی اوقات برگه های مخفی را (به صلاحدید خود) مسدود می کنند و دور می اندازند، اما توسعه دهندگان راهی برای اطلاع از زمان وقوع این اتفاق ندارند.
در Chrome 68، توسعهدهندگان اکنون میتوانند با گوش دادن به freeze
و resume
رویدادها در document
مشاهده کنند که یک برگه مخفی ثابت و غیر منجمد میشود.
document.addEventListener('freeze', (event) => {
// The page is now frozen.
});
document.addEventListener('resume', (event) => {
// The page has been unfrozen.
});
از Chrome 68 شی document
اکنون شامل یک ویژگی wasDiscarded
در کروم دسکتاپ است ( پشتیبانی از Android در این شماره ردیابی می شود ). برای تعیین اینکه آیا یک صفحه زمانی که در یک برگه مخفی است کنار گذاشته شده است یا خیر، می توانید مقدار این ویژگی را در زمان بارگذاری صفحه بررسی کنید (توجه داشته باشید: برای استفاده مجدد، صفحات حذف شده باید دوباره بارگیری شوند).
if (document.wasDiscarded) {
// Page was previously discarded by the browser while in a hidden tab.
}
برای مشاوره در مورد کارهایی که در freeze
و resume
رویدادها مهم هستند، و همچنین نحوه مدیریت و آماده شدن برای صفحاتی که دور ریخته می شوند، توصیه های برنامه نویس برای هر ایالت را ببینید.
چندین بخش بعدی یک نمای کلی از نحوه تناسب این ویژگی های جدید با وضعیت ها و رویدادهای پلت فرم وب موجود ارائه می دهد.
نحوه مشاهده وضعیت های چرخه عمر صفحه در کد
در حالتهای فعال ، غیرفعال و پنهان ، میتوان کد جاوا اسکریپت را اجرا کرد که وضعیت چرخه حیات صفحه را از APIهای پلتفرم وب موجود تعیین میکند.
const getState = () => {
if (document.visibilityState === 'hidden') {
return 'hidden';
}
if (document.hasFocus()) {
return 'active';
}
return 'passive';
};
از طرف دیگر، حالتهای یخزده و خاتمهیافته ، تنها در شنونده رویداد مربوطه ( freeze
و pagehide
) با تغییر وضعیت قابل شناسایی هستند.
نحوه مشاهده تغییرات حالت
با استفاده از تابع getState()
که قبلا تعریف شده بود، می توانید تمام تغییرات حالت چرخه عمر صفحه را با کد زیر مشاهده کنید.
// Stores the initial state using the `getState()` function (defined above).
let state = getState();
// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
const prevState = state;
if (nextState !== prevState) {
console.log(`State change: ${prevState} >>> ${nextState}`);
state = nextState;
}
};
// Options used for all event listeners.
const opts = {capture: true};
// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
window.addEventListener(type, () => logStateChange(getState()), opts);
});
// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
// In the freeze event, the next state is always frozen.
logStateChange('frozen');
}, opts);
window.addEventListener('pagehide', (event) => {
// If the event's persisted property is `true` the page is about
// to enter the back/forward cache, which is also in the frozen state.
// If the event's persisted property is not `true` the page is
// about to be unloaded.
logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);
این کد سه کار را انجام می دهد:
- با استفاده از تابع
getState()
حالت اولیه را تنظیم می کند. - تابعی را تعریف می کند که حالت بعدی را می پذیرد و در صورت تغییر، تغییرات وضعیت را به کنسول ثبت می کند.
- شنوندگان رویداد را برای همه رویدادهای چرخه حیات ضروری اضافه می کند، که به نوبه خود
logStateChange()
فراخوانی می کند و در حالت بعدی ارسال می شود.
یک نکته در مورد کد این است که تمام شنوندگان رویداد به window
اضافه می شوند و همه آنها {capture: true}
پاس می کنند. چند دلیل برای این وجود دارد:
- همه رویدادهای چرخه عمر صفحه هدف یکسانی ندارند.
pagehide
وpageshow
درwindow
فعال می شوند.visibilitychange
،freeze
وresume
رویdocument
فعال میشوند وfocus
وblur
روی عناصر DOM مربوطه فعال میشوند. - بیشتر این رویدادها حباب نمیشوند، به این معنی که اضافه کردن شنوندگان رویداد غیرمجاز به یک عنصر جد مشترک و مشاهده همه آنها غیرممکن است.
- مرحله ضبط قبل از مرحله هدف یا حباب اجرا می شود، بنابراین افزودن شنوندگان به آنجا کمک می کند تا اطمینان حاصل شود که قبل از اینکه سایر کدها بتوانند آنها را لغو کنند، اجرا می شوند.
توصیه های توسعه دهنده برای هر ایالت
به عنوان توسعهدهندگان، مهم است که وضعیتهای چرخه عمر صفحه را درک کنید و بدانید که چگونه آنها را در کد مشاهده کنید، زیرا نوع کاری که باید (و نباید) انجام دهید تا حد زیادی به وضعیت صفحه شما بستگی دارد.
به عنوان مثال، اگر صفحه در حالت مخفی است، واضح است که نمایش یک اعلان گذرا به کاربر منطقی نیست. در حالی که این مثال کاملا واضح است، توصیه های دیگری وجود دارد که چندان واضح نیستند که ارزش شمردن را دارند.
ایالت | توصیه های توسعه دهندگان |
---|---|
Active | حالت فعال بحرانی ترین زمان برای کاربر است و بنابراین مهم ترین زمان برای پاسخگویی صفحه شما به ورودی کاربر است . هر کار غیر UI که ممکن است رشته اصلی را مسدود کند باید به دورههای بیحرکت اولویت داده شود یا برای یک وبکارگر بارگذاری شود . |
Passive | در حالت غیرفعال ، کاربر با صفحه تعامل ندارد، اما همچنان می تواند آن را ببیند. این بدان معناست که بهروزرسانیها و انیمیشنهای رابط کاربری همچنان باید روان باشند، اما زمان وقوع این بهروزرسانیها کمتر مهم است. هنگامی که صفحه از فعال به غیرفعال تغییر می کند، زمان خوبی برای حفظ وضعیت ذخیره نشده برنامه است. |
هنگامی که صفحه از حالت غیرفعال به پنهان تغییر می کند، این امکان وجود دارد که کاربر دیگر با آن ارتباط برقرار نکند تا زمانی که دوباره بارگیری شود. انتقال به حالت پنهان اغلب آخرین تغییر حالت است که به طور قابل اعتماد توسط توسعه دهندگان قابل مشاهده است (این امر به ویژه در تلفن همراه صادق است، زیرا کاربران می توانند برگه ها یا خود برنامه مرورگر را ببندند، و رویدادهای این بدان معنی است که شما باید حالت پنهان را به عنوان پایان احتمالی جلسه کاربر در نظر بگیرید. به عبارت دیگر، هر حالت برنامه ذخیره نشده را حفظ کنید و داده های تحلیلی ارسال نشده را ارسال کنید. همچنین باید بهروزرسانیهای رابط کاربری را متوقف کنید (زیرا کاربر آنها را نمیبیند)، و باید کارهایی را که کاربر نمیخواهد در پسزمینه اجرا شود، متوقف کنید. | |
Frozen | در حالت یخزده ، وظایف قابل انجماد در صفهای وظیفه تا زمانی که صفحه از حالت ثابت خارج شود، به حالت تعلیق در میآیند - که ممکن است هرگز اتفاق نیفتد (مثلاً اگر صفحه دور ریخته شود). این بدان معناست که وقتی صفحه از حالت مخفی به ثابت تبدیل میشود، ضروری است که تایمرها را متوقف کنید یا اتصالاتی را که در صورت ثابت ماندن، میتواند بر سایر برگههای باز در همان مبدا تأثیر بگذارد یا بر توانایی مرورگر برای قرار دادن صفحه در پشت یا تأثیر بگذارد، قطع کنید. کش فوروارد . به ویژه، مهم است که شما:
همچنین باید هر وضعیت نمای پویا (مثلاً موقعیت اسکرول در یک نمای لیست نامحدود) را در اگر صفحه از حالت ثابت به حالت مخفی تبدیل شد، میتوانید اتصالات بسته را دوباره باز کنید یا هر نظرسنجی را که زمانی که صفحه در ابتدا ثابت بود متوقف کردهاید، دوباره راهاندازی کنید. |
Terminated | معمولاً هنگام انتقال صفحه به حالت پایان یافته ، نیازی به انجام هیچ اقدامی نیست. از آنجایی که صفحاتی که در نتیجه اقدام کاربر بارگیری می شوند همیشه قبل از وارد شدن به حالت خاتمه از حالت پنهان عبور می کنند، حالت پنهان جایی است که منطق پایان جلسه (مثلاً وضعیت برنامه مداوم و گزارش به تجزیه و تحلیل) باید انجام شود. همچنین (همانطور که در توصیههای مربوط به حالت پنهان ذکر شد)، برای توسعهدهندگان بسیار مهم است که بدانند انتقال به حالت پایانیافته در بسیاری از موارد (بهویژه در تلفن همراه) بهطور قابل اعتماد قابل تشخیص نیست، بنابراین توسعهدهندگانی که به رویدادهای پایان (مثلاً |
Discarded | حالت حذف شده توسط توسعه دهندگان در زمانی که یک صفحه حذف می شود قابل مشاهده نیست. این به این دلیل است که صفحات معمولاً تحت محدودیت منابع کنار گذاشته می شوند، و باز کردن یک صفحه فقط برای اجازه دادن به اسکریپت برای اجرا در پاسخ به یک رویداد کنار گذاشته شده به سادگی در بیشتر موارد امکان پذیر نیست. در نتیجه، باید برای احتمال نادیده گرفتن تغییر از حالت مخفی به ثابت آماده شوید و سپس می توانید با بررسی |
بار دیگر، از آنجایی که قابلیت اطمینان و ترتیب رویدادهای چرخه حیات به طور مداوم در همه مرورگرها اجرا نمی شود، ساده ترین راه برای پیروی از توصیه های جدول استفاده از PageLifecycle.js است.
APIهای چرخه عمر قدیمی که باید اجتناب کنید
تا جایی که ممکن است باید از اتفاقات زیر اجتناب شود.
رویداد تخلیه
بسیاری از توسعه دهندگان رویداد unload
را به عنوان یک تماس تضمین شده در نظر می گیرند و از آن به عنوان سیگنال پایان جلسه برای ذخیره وضعیت و ارسال داده های تجزیه و تحلیل استفاده می کنند، اما انجام این کار به خصوص در تلفن همراه بسیار غیر قابل اعتماد است! رویداد unload
در بسیاری از موقعیتهای بارگیری معمولی فعال نمیشود، از جمله بستن یک برگه از تعویضکننده برگه در تلفن همراه یا بستن برنامه مرورگر از تعویضکننده برنامه.
به همین دلیل، همیشه بهتر است برای تعیین زمان پایان جلسه به رویداد visibilitychange
تکیه کنید و حالت پنهان را آخرین زمان قابل اعتماد برای ذخیره اطلاعات برنامه و کاربر در نظر بگیرید.
علاوه بر این، صرف حضور یک کنترلکننده رویداد unload
(از طریق onunload
یا addEventListener()
) میتواند مانع از این میشود که مرورگرها بتوانند صفحات را در حافظه پنهان عقب و جلو برای بارگیری سریعتر به عقب و جلو قرار دهند.
در همه مرورگرهای مدرن، توصیه میشود که همیشه از رویداد pagehide
برای شناسایی بارگیریهای احتمالی صفحه (معروف به حالت پایان یافته ) به جای رویداد unload
استفاده شود. اگر نیاز به پشتیبانی از اینترنت اکسپلورر نسخه 10 و پایینتر دارید، باید قابلیت تشخیص رویداد pagehide
را داشته باشید و فقط در صورتی از unload
استفاده کنید که مرورگر از pagehide
پشتیبانی نمیکند:
const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
window.addEventListener(terminationEvent, (event) => {
// Note: if the browser is able to cache the page, `event.persisted`
// is `true`, and the state is frozen rather than terminated.
});
رویداد قبل از بارگیری
رویداد beforeunload
مشکلی مشابه با رویداد unload
دارد، زیرا از نظر تاریخی، وجود یک رویداد beforeunload
میتواند از واجد شرایط بودن صفحات برای کش عقب/ جلو جلوگیری کند. مرورگرهای مدرن این محدودیت را ندارند. اگرچه برخی از مرورگرها، به عنوان یک اقدام احتیاطی، هنگام تلاش برای قرار دادن یک صفحه در حافظه پنهان عقب/ جلو، رویداد beforeunload
را فعال نمیکنند، به این معنی که رویداد به عنوان سیگنال پایان جلسه قابل اعتماد نیست. علاوه بر این، برخی از مرورگرها (از جمله Chrome ) قبل از اینکه اجازه دهند رویداد beforeunload
فعال شود، نیاز به تعامل با کاربر در صفحه دارند که بر قابلیت اطمینان آن تأثیر می گذارد.
یک تفاوت بین beforeunload
و unload
این است که استفاده های قانونی از beforeunload
وجود دارد. به عنوان مثال، هنگامی که می خواهید به کاربر هشدار دهید که تغییرات ذخیره نشده ای دارد، اگر به بارگیری صفحه ادامه دهد، آنها را از دست خواهند داد.
از آنجایی که دلایل معتبری برای استفاده beforeunload
وجود دارد، توصیه میشود فقط زمانی که کاربر تغییرات ذخیرهنشدهای دارد، شنوندههای beforeunload
را اضافه کنید و بلافاصله پس از ذخیره آنها را حذف کنید.
به عبارت دیگر، این کار را انجام ندهید (زیرا یک شنونده beforeunload
بدون قید و شرط اضافه می کند):
addEventListener('beforeunload', (event) => {
// A function that returns `true` if the page has unsaved changes.
if (pageHasUnsavedChanges()) {
event.preventDefault();
// Legacy support for older browsers.
return (event.returnValue = true);
}
});
در عوض این کار را انجام دهید (زیرا فقط در صورت نیاز شنونده beforeunload
را اضافه می کند و در صورت عدم نیاز آن را حذف می کند):
const beforeUnloadListener = (event) => {
event.preventDefault();
// Legacy support for older browsers.
return (event.returnValue = true);
};
// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
addEventListener('beforeunload', beforeUnloadListener);
});
// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
removeEventListener('beforeunload', beforeUnloadListener);
});
سوالات متداول
چرا حالت "بارگیری" وجود ندارد؟
Page Lifecycle API حالتها را مجزا و انحصاری متقابل تعریف می کند. از آنجایی که یک صفحه میتواند در حالت فعال، غیرفعال یا پنهان بارگیری شود، و از آنجایی که میتواند حالتها را تغییر دهد - یا حتی خاتمه یابد - قبل از اتمام بارگذاری، یک حالت بارگذاری جداگانه در این پارادایم معنا ندارد.
صفحه من وقتی پنهان است کارهای مهمی انجام می دهد، چگونه می توانم جلوی فریز یا دور انداختن آن را بگیرم؟
دلایل قانونی زیادی وجود دارد که صفحات وب نباید هنگام اجرا در حالت مخفی مسدود شوند. بارزترین مثال اپلیکیشنی است که موسیقی پخش می کند.
همچنین شرایطی وجود دارد که دور انداختن صفحه برای Chrome خطرناک است، مثلاً اگر حاوی فرمی با ورودی کاربر ارسالنشده باشد، یا اگر دارای یک کنترل کننده beforeunload
باشد که هنگام بارگیری صفحه هشدار میدهد.
در حال حاضر، کروم در حذف صفحات محافظه کارانه عمل می کند و تنها زمانی این کار را انجام می دهد که مطمئن باشد بر کاربران تأثیری نخواهد گذاشت. برای مثال، صفحاتی که مشاهده شدهاند هر یک از کارهای زیر را در حالت مخفی انجام میدهند، کنار گذاشته نمیشوند، مگر اینکه تحت محدودیت شدید منابع باشند:
- پخش صدا
- با استفاده از WebRTC
- به روز رسانی عنوان جدول یا فاویکون
- نمایش هشدارها
- ارسال اعلان های فشار
برای ویژگیهای فهرست فعلی که برای تعیین اینکه آیا یک برگه را میتوان بهطور ایمن ثابت کرد یا دور انداخت، ببینید: Heuristics for Freezing & Discarding در Chrome.
کش عقب و جلو اصطلاحی است که برای توصیف بهینهسازی ناوبری استفاده میشود که برخی از مرورگرها اجرا میکنند که استفاده از دکمههای برگشت و جلو را سریعتر میکند.
هنگامی که کاربر از صفحه ای دور می شود، این مرورگرها نسخه ای از آن صفحه را مسدود می کنند تا در صورتی که کاربر با استفاده از دکمه های برگشت یا جلو به عقب برگردد، به سرعت از سر گرفته شود. به یاد داشته باشید که افزودن یک کنترل کننده رویداد unload
از امکان این بهینه سازی جلوگیری می کند .
برای همه مقاصد، این انجماد از نظر عملکردی مشابه مرورگرهای انجماد برای حفظ CPU/باتری است. به همین دلیل بخشی از حالت چرخه حیات منجمد در نظر گرفته می شود.
اگر نمیتوانم APIهای ناهمزمان را در حالتهای ثابت یا خاتمه اجرا کنم، چگونه میتوانم دادهها را در IndexedDB ذخیره کنم؟
در حالتهای ثابت و خاتمهیافته، وظایف قابل انجماد در صفهای وظیفه صفحه به حالت تعلیق در میآیند، به این معنی که APIهای ناهمزمان و مبتنی بر تماس مانند IndexedDB قابل استفاده نیستند.
در آینده، یک متد commit()
به اشیاء IDBTransaction
اضافه خواهیم کرد، که به توسعه دهندگان راهی می دهد تا تراکنش هایی را که به طور موثر فقط نوشتن هستند و نیازی به callback ندارند، انجام دهند. به عبارت دیگر، اگر توسعهدهنده فقط دادهها را در IndexedDB مینویسد و یک تراکنش پیچیده شامل خواندن و نوشتن را انجام نمیدهد، متد commit()
میتواند قبل از تعلیق صفهای وظیفه به پایان برسد (با فرض اینکه پایگاه داده IndexedDB از قبل باز باشد).
با این حال، برای کدهایی که باید امروز کار کنند، توسعه دهندگان دو گزینه دارند:
- از فضای ذخیرهسازی جلسه استفاده کنید: ذخیرهسازی جلسه همزمان است و در بین صفحات نادیده گرفته میشود.
- از IndexedDB از سرویسکار خود استفاده کنید: یک سرویسگر میتواند دادهها را پس از پایان یا دور انداختن صفحه در IndexedDB ذخیره کند. در شنونده رویداد
freeze
یاpagehide
میتوانید دادهها را از طریقpostMessage()
به سرویسکار خود ارسال کنید و سرویسکار میتواند ذخیره دادهها را انجام دهد.
آزمایش برنامه شما در حالت یخ زده و دور انداخته شده
برای آزمایش نحوه عملکرد برنامهتان در حالتهای ثابت و دور انداختهشده، میتوانید از chrome://discards
دیدن کنید تا در واقع هر یک از برگههای باز خود را ثابت یا نادیده بگیرید.
این به شما این امکان را می دهد که مطمئن شوید صفحه شما به درستی رویدادهای freeze
و resume
و همچنین پرچم document.wasDiscarded
را هنگام بارگیری مجدد صفحات پس از رد کردن، مدیریت می کند.
خلاصه
توسعهدهندگانی که میخواهند به منابع سیستمی دستگاههای کاربر خود احترام بگذارند، باید برنامههای خود را با در نظر گرفتن حالتهای چرخه عمر صفحه بسازند. بسیار مهم است که صفحات وب منابع بیش از حد سیستم را در شرایطی که کاربر انتظار ندارد مصرف نکنند.
هرچه توسعهدهندگان بیشتر شروع به پیادهسازی APIهای جدید Page Lifecycle کنند، برای مرورگرها ایمنتر میشوند که صفحاتی را که استفاده نمیشوند مسدود کرده و دور بیندازند. این بدان معناست که مرورگرها حافظه، CPU، باتری و منابع شبکه کمتری مصرف می کنند که برای کاربران یک پیروزی محسوب می شود.