یکی از چیزهایی که میتواند در عملکرد برنامه مشکل ایجاد کند گیرندههای ورودی هستند. به تابعهایی که تنظیم میکنید در هنگام ورودیهای کاربر مثل کلیک و… اجرا شوند input handler یا گیرندهی ورودی میگوییم. این گیرندهها میتوانند جلوی کامل شدن فریم را بگیرند و باعث انجام صفحهآراییهای غیر ضروری شوند.
- جلوی گیرندههای ورودی طولانی را بگیرید؛ چون میتوانند اسکرول را قفل کنند.
- در گیرندههای ورودی تغییرات استایلی ندهید.
- گیرندههای ورودی را به تأخیر بیندازید؛ مقادیری که مربوط به event میشود و لازم دارید ذخیره کنید و در آغاز فریم بعدی (با requestAnimationFrame) دستورات خود را اجرا کنید.
جلوی گیرندههای ورودی طولانی را بگیرید
در سریعترین حالت، وقتی که کاربر به صفحه سیخ میزند، compositor thread (یعنی همان thread که مرحلهی ترکیب در آن انجام میشود) ورودی کاربر را میگیرد و صفحه را برای اسکرول حرکت میدهد. در این حین اگر مراحل JavaScript، محاسبهی استایل، صفحهآرایی یا ترسیم انجام شده باشد، 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);
این کار باعث سبک شدن گیرندههای ورودی شما میشود، و این خیلی خوب است چون الآن کدهای محاسباتی سنگین، چیزهایی مثل اسکرول را قفل نمیکند.