أحمد حايس
الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
البرمجة بالعربي

Debounce وThrottle: إزاي توقف صندوق البحث من ضرب سيرفرك 40 مرة في الثانية

متوسط14 يوليو 20264 دقائق قراءة
Debounce وThrottle: إزاي توقف صندوق البحث من ضرب سيرفرك 40 مرة في الثانية

هذا المقال يتطلب مستوى: متوسط

لو صندوق البحث عندك بيبعت طلب للـ API مع كل حرف بيكتبه المستخدم، انت بتضرب السيرفر عشرات المرات في كل بحث واحد. الحل مش تكبير السيرفر، الحل سطرين كود: Debounce أو Throttle. المقال ده هيوريك الفرق بينهم بالظبط، وإمتى تستخدم كل واحد، وكود شغّال تنسخه دلوقتي.

المشكلة باختصار

المستخدم بيكتب "react hooks tutorial" في خانة البحث. دي حوالي 20 حرف. لو ربطت الـ API بحدث input على طول، هيتبعت 20 طلب في أقل من 3 ثواني. تسعة عشر منهم نتيجتهم اترمت قبل ما توصل الشاشة، لأن المستخدم لسه بيكتب.

ده مش مثال نظري. لو عندك موقع بـ 50 ألف مستخدم في اليوم بيعملوا بحث، والمتوسط 15 حرف للبحث الواحد، انت بتعمل 15 ضعف الطلبات اللي محتاجها فعلاً. ده بيترجم لفاتورة سيرفر أعلى، وضغط على قاعدة البيانات، وتجربة أبطأ.

محرر أكواد يعرض دالة جافاسكريبت لمعالجة حدث الكتابة في حقل بحث

الفكرة الأساسية بمثال بسيط

تخيّل باب المصعد. كل ما حد جديد يدخل، الباب بيستنى شوية قبل ما يقفل. طول ما في ناس داخلة، الباب فاضل مفتوح. لما يعدّي وقت من غير أي حركة، الباب يقفل والمصعد يتحرك مرة واحدة. ده بالظبط الـ Debounce: استنى لحد ما الأحداث تهدا، وبعدها نفّذ مرة واحدة.

الـ Throttle مختلف. تخيّل صنبور مياه مفتوح على آخره، وانت حاطط قدامه منظّم بيسمح بنقطة كل ثانية بالظبط. مهما اندفعت المية، المخرج ثابت: نقطة كل ثانية. يعني نفّذ بمعدل ثابت، ومتزوّدش عنه مهما زادت الأحداث.

دلوقتي التعريف العلمي الدقيق. Debounce بيأجّل تنفيذ الدالة لحد ما يعدّي وقت محدد (مثلاً 300 مللي ثانية) من غير أي استدعاء جديد. أي استدعاء جديد بيصفّر العدّاد. النتيجة: الدالة بتشتغل مرة واحدة بعد آخر حدث. Throttle بيضمن إن الدالة متشتغلش أكتر من مرة كل فترة محددة، بغضّ النظر عن عدد الأحداث اللي وصلت في الفترة دي.

الكود: Debounce

ده تطبيق كامل شغّال في المتصفح، بدون أي مكتبة خارجية:

JavaScript
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 وmousemove. حدث الـ scroll لوحده ممكن يشتغل من 30 لـ 100 مرة في الثانية:

JavaScript
function throttle(fn, wait) {
  let last = 0;
  return function (...args) {
    const now = Date.now();
    if (now - last >= wait) {
      last = now;
      fn.apply(this, args);
    }
  };
}

// حدّث شريط تقدّم القراءة 5 مرات في الثانية بدل 60
window.addEventListener("scroll", throttle(() => {
  updateReadingProgress();
}, 200));

هنا بنثبّت المعدل عند 5 استدعاءات في الثانية (كل 200ms). لو كان الـ scroll بيشتغل 60 مرة في الثانية، احنا وفّرنا حوالي 91% من عمليات إعادة الرسم، والصفحة فضلت سلسة.

إزاي تختار بينهم

  • استخدم Debounce لما يهمّك آخر قيمة بس: البحث الفوري، حفظ المسودّة تلقائيًا، التحقق من صحة حقل بعد ما المستخدم يخلّص كتابة.
  • استخدم Throttle لما يهمّك تحديث منتظم أثناء الحدث: شريط تقدّم، تتبّع موضع الماوس، تحميل عناصر جديدة عند التمرير.

الـ trade-off هنا

مفيش حل ببلاش. الـ Debounce بيضيف تأخير محسوس: لو حطيت 300ms، المستخدم هيشوف النتايج بعد 300ms من آخر حرف. لو زوّدت الرقم بتوفّر طلبات أكتر بس التجربة بتحس أبطأ. الافتراض هنا إن 200 لـ 350 مللي ثانية رقم مقبول لمعظم واجهات البحث.

الـ Throttle بيكسب استجابة منتظمة، بس التطبيق البسيط اللي فوق ممكن يفوّت آخر حدث. لو المستخدم وقف التمرير في نص فترة الـ 200ms، آخر تحديث ممكن ميحصلش. مكتبة زي Lodash بتحل ده بخيارات leading وtrailing.

متى لا تستخدم هذه الطريقة

متعملش Debounce لزرار إرسال عادي أو ضغطة واحدة، هتضيف تأخير من غير أي فايدة. ومتستخدمش Throttle لو الشغل اللي بيتنفّذ رخيص جدًا وبيتم محليًا. والأهم: الطريقة دي للمتصفح وأحداثه. لو انت على السيرفر وعايز تحكم في معدل الطلبات، ده شغل rate limiter أو طابور، مش debounce بسيط في الذاكرة.

الخطوة التالية

افتح أبطأ حقل بحث أو أثقل معالج scroll في مشروعك دلوقتي، ولفّ الدالة بـ debounce أو throttle على حسب الحالة. افتح تبويب Network في المتصفح قبل وبعد، وقارن عدد الطلبات.

مصادر

  • MDN Web Docs — setTimeout() وaddEventListener(): توثيق المؤقّتات وربط الأحداث.
  • Lodash Documentation — _.debounce و_.throttle: خيارات leading وtrailing وmaxWait.
  • CSS-Tricks — Debouncing and Throttling Explained Through Examples بقلم David Corbacho.
  • MDN Web Docs — input event: سلوك حدث الكتابة في حقول الإدخال.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة