المستوى: مبتدئ
لو search box في موقعك بيبعت طلب للسيرفر بعد كل حرف، الزائر اللي بيكتب "react hooks performance" بيعمل 24 طلب في ثانيتين. ضرب ألف مستخدم متزامن، يبقى 24,000 طلب على API محتاج يخدم نتيجة واحدة. Debouncing بـ 8 سطور JavaScript بينزّل الرقم ده لـ 1,000 طلب فقط. توفير 95.8% بدون لمس باك إند ولا قاعدة بيانات.
Debouncing vs Throttling: الفرق وامتى تستخدم كل واحد
المشكلة باختصار
أحداث JavaScript الشائعة بتتفعّل بمعدلات مرتفعة جدًا: scroll ممكن يطلق 60 مرة في الثانية، mousemove ممكن يوصل 200، وinput بيتفعّل مع كل ضغطة زرار. لو ربطت دالة ثقيلة — fetch، حساب، update لـ DOM — بأي event منهم مباشرة، هتلاقي الـ CPU بياكل، الواجهة بتتجمّد، والـ network بيتلوث بطلبات مفيش لازمة لها. Debouncing وThrottling حلّان مختلفان لنفس المشكلة بفلسفتين مختلفتين، ومعرفة الفرق بينهم بيوفر عليك أخطاء كبيرة.
المثال اللي هيخلّي الفكرة واضحة
تخيّل عندك جرس باب فيلا. كل دوسة بترن مرة. ولاد الجيران فاكرين الموضوع لعبة وقاعدين يدوسوا 50 مرة في 5 ثواني. عندك حلين:
- Debouncing: الجرس مش هيرن إلا بعد ما يفضى 3 ثواني من غير ضغط. لو الواد دوس 50 مرة وفضى، هيسمع رنّة واحدة بس بعد آخر دوسة بـ 3 ثواني. الفلسفة هنا: "استنى لحد ما المستخدم يخلّص".
- Throttling: الجرس بيرن مرة واحدة كل 3 ثواني مهما حصل. في الـ 5 ثواني هيرن مرتين كحد أقصى. الفلسفة: "اشتغل بإيقاع ثابت ومتسمعش الباقي".
الفرق الجوهري في سطر واحد: Debouncing بيستنى السكون. Throttling بيشتغل بإيقاع.
التعريف العلمي الدقيق
Debounce(fn, delay): دالة بترجع نسخة جديدة من fn. كل مرة بتتنادى النسخة دي بتلغي أي استدعاء معلّق وتبدأ عداد جديد بـ delay مللي ثانية. لو مفيش استدعاء جديد قبل ما العداد يخلص، الدالة الأصلية بتتنفذ. النتيجة: الدالة بتشتغل مرة واحدة بعد آخر استدعاء بـ delay.
Throttle(fn, interval): دالة بترجع نسخة جديدة من fn. النسخة دي بتسمح بأول استدعاء يمر، وبعد كده بترفض أي استدعاء جديد قبل مرور interval مللي ثانية من آخر تنفيذ. النتيجة: الدالة بتشتغل بمعدل أقصى مرة كل interval.
الكود الفعلي (8 سطور لكل واحد)
الـ debounce function بدون أي مكتبة:
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}