هذا المقال يتطلب مستوى: متوسط
لو صندوق البحث عندك بيبعت طلب للـ API مع كل حرف بيكتبه المستخدم، انت بتضرب السيرفر عشرات المرات في كل بحث واحد. الحل مش تكبير السيرفر، الحل سطرين كود: Debounce أو Throttle. المقال ده هيوريك الفرق بينهم بالظبط، وإمتى تستخدم كل واحد، وكود شغّال تنسخه دلوقتي.
المشكلة باختصار
المستخدم بيكتب "react hooks tutorial" في خانة البحث. دي حوالي 20 حرف. لو ربطت الـ API بحدث input على طول، هيتبعت 20 طلب في أقل من 3 ثواني. تسعة عشر منهم نتيجتهم اترمت قبل ما توصل الشاشة، لأن المستخدم لسه بيكتب.
ده مش مثال نظري. لو عندك موقع بـ 50 ألف مستخدم في اليوم بيعملوا بحث، والمتوسط 15 حرف للبحث الواحد، انت بتعمل 15 ضعف الطلبات اللي محتاجها فعلاً. ده بيترجم لفاتورة سيرفر أعلى، وضغط على قاعدة البيانات، وتجربة أبطأ.
الفكرة الأساسية بمثال بسيط
تخيّل باب المصعد. كل ما حد جديد يدخل، الباب بيستنى شوية قبل ما يقفل. طول ما في ناس داخلة، الباب فاضل مفتوح. لما يعدّي وقت من غير أي حركة، الباب يقفل والمصعد يتحرك مرة واحدة. ده بالظبط الـ Debounce: استنى لحد ما الأحداث تهدا، وبعدها نفّذ مرة واحدة.
الـ Throttle مختلف. تخيّل صنبور مياه مفتوح على آخره، وانت حاطط قدامه منظّم بيسمح بنقطة كل ثانية بالظبط. مهما اندفعت المية، المخرج ثابت: نقطة كل ثانية. يعني نفّذ بمعدل ثابت، ومتزوّدش عنه مهما زادت الأحداث.
دلوقتي التعريف العلمي الدقيق. Debounce بيأجّل تنفيذ الدالة لحد ما يعدّي وقت محدد (مثلاً 300 مللي ثانية) من غير أي استدعاء جديد. أي استدعاء جديد بيصفّر العدّاد. النتيجة: الدالة بتشتغل مرة واحدة بعد آخر حدث. Throttle بيضمن إن الدالة متشتغلش أكتر من مرة كل فترة محددة، بغضّ النظر عن عدد الأحداث اللي وصلت في الفترة دي.
الكود: Debounce
ده تطبيق كامل شغّال في المتصفح، بدون أي مكتبة خارجية:
function debounce(fn, wait) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, wait);
};
}
// بحث لا يضرب الـ API إلا بعد توقف الكتابة 300ms
const onSearch = debounce((query) => {
fetch("/api/search?q=" + encodeURIComponent(query));
}, 300);
input.addEventListener("input", (e) => onSearch(e.target.value));النتيجة المقاسة: بحث "react hooks tutorial" ينزل من 20 طلب لطلب واحد. توفير حوالي 95% من طلبات البحث.
الكود: Throttle
الـ Throttle مناسب للأحداث اللي بتتكرر بسرعة جنونية زي scroll وresize و. حدث الـ scroll لوحده ممكن يشتغل من 30 لـ 100 مرة في الثانية: