گیرنده‌های ورودی را به تأخیر بیندازید

یکی از چیزهایی که می‌تواند در عملکرد برنامه مشکل ایجاد کند گیرنده‌های ورودی هستند. به تابع‌هایی که تنظیم می‌کنید در هنگام ورودی‌های کاربر مثل کلیک و… اجرا شوند input handler یا گیرنده‌ی ورودی می‌گوییم. این گیرنده‌ها می‌توانند جلوی کامل شدن فریم را بگیرند و باعث انجام صفحه‌آرایی‌های غیر ضروری شوند.

خلاصه

 

  • جلوی گیرنده‌های ورودی طولانی را بگیرید؛ چون می‌توانند اسکرول را قفل کنند.
  • در گیرنده‌های ورودی تغییرات استایلی ندهید.
  • گیرنده‌های ورودی را به تأخیر بیندازید؛ مقادیری که مربوط به event می‌شود و لازم دارید ذخیره کنید و در آغاز فریم بعدی (با requestAnimationFrame) دستورات خود را اجرا کنید.

جلوی گیرنده‌های ورودی طولانی را بگیرید

در سریع‌ترین حالت، وقتی که کاربر به صفحه سیخ می‌زند، compositor thread (یعنی همان thread که مرحله‌ی ترکیب در آن انجام می‌شود) ورودی کاربر را می‌گیرد و صفحه را برای اسکرول حرکت می‌دهد. در این حین اگر مراحل JavaScript، محاسبه‌ی استایل، صفحه‌آرایی یا ترسیم انجام شده باشد، thread اصلی لازم نیست هیچ کاری انجام بدهد.

اسکرول در compositor thread

حالا اگر شما در رویدادهایی مثل touchstart، touchmove یا touchend یک گیرنده‌ی ورودی  تنظیم کرده باشید، در این حالت compositor thread مجبور است منتظر بماند تا گیرنده‌ی ورودی شما اجرا شود چون شاید شما بخواهید preventDefault() را اجرا کنید تا جلوی اسکرول را بگیرید. حتّی اگر شما اصلاً preventDefault() را استفاده نکرده باشید باز هم باید صبر کند، و در این حین اسکرول قفل می‌شود و ممکن است فریم‌ها از بین بروند و صفحه به کُندی کار کند.

گیرنده‌ی ورودی اسکرول را قفل می‌کند

به طور خلاصه، گیرنده‌های ورودی شما باید خیلی سریع اجرا شوند و به Compositor thread اجازه دهند کارش را انجام دهد.

در گیرنده‌های ورودی تغییرات استایلی انجام ندهید

گیرنده‌های ورودی طوری تنظیم شده‌اند که قبل از هر requestAnimationFrame اجرا شوند.

اگر در این گیرنده‌ها تغییرات ظاهری اعمال کنید، و از طرفی در یک جای دیگر دستوراتی در یک requestAnimationFrame بخواهد مقادیر مربوط به استایل را بخواند، همان طور که در قسمت «بهینه‌سازی مرحله‌ی صفحه‌آرایی» گفته‌ایم مشکل «همگام‌سازی اجباری صفحه‌آرایی» اتّفاق می‌افتد، زیرا قبل از اینکه دستورات requestAnimationFrame اجرا شود، دستورات گیرنده‌ی ورودی شما اجرا می‌شود.

همگام‌سازی اجباری صفحه آرایی در گیرنده‌های ورودی

گیرنده‌های ورودی‌تان را به تأخیر بیندازید

راه حل هر دو مشکل قبلی یک چیز است: شما همیشه باید تغییرات ظاهری را به تأخیر بیندازید برای فریم بعدی، با استفاده از requestAnimationFrame:

function onScroll (evt) {

  // مقدار اسکرول را ذخیره می‌کنیم برای بعد
  lastScrollY = window.scrollY;

  // جلوی چند بار اجرا شدن requestAnimationFrame را می‌گیریم
  if (scheduledAnimationFrame)
    return;

  scheduledAnimationFrame = true;
  requestAnimationFrame(readAndUpdatePage);
}

window.addEventListener('scroll', onScroll);

این کار باعث سبک شدن گیرنده‌های ورودی شما می‌شود، و این خیلی خوب است چون الآن کدهای محاسباتی سنگین، چیزهایی مثل اسکرول را قفل نمی‌کند.

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *