تحديد الطلبات في JavaScript: كيف لا ندع API ينهار

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Rate limiting و throttling في JavaScript: الحماية والأداء

\n\n

هل تساءلت يومًا لماذا بعد عشرات النقرات السريعة على زر "إرسال" تتوقف خدمتك المفضلة فجأة عن الاستجابة؟ أو لماذا تطلب منك بعض المواقع "الانتظار لمدة 30 ثانية" قبل إعادة إرسال النموذج؟ الإجابة تكمن في آليتين قويتين تنقذان الواجهة الخلفية من التحميل الزائد والمستخدمين من "الأخطاء": rate limiting و throttling.

\n\n

في هذه المقالة، سنشرح كيفية تطبيق هذه التقنيات باستخدام JavaScript الخالص و Node.js. ستتعرف على الفرق بين throttle و debounce، وكيفية كتابة rate limiter بسيط لـ API، ولماذا سيعمل موقعك بشكل أسرع. هيا بنا!

\n\n

ما هو rate limiting ولماذا هو مطلوب؟

\n\n

Rate limiting (تحديد سرعة الطلبات) هو آلية حماية تحد من عدد الطلبات من العميل (أو عنوان IP) خلال فترة زمنية محددة. تخيل حاجزًا: يمكن للسيارة المرور، ولكن مرة واحدة فقط كل 10 ثوانٍ.

\n\n

أين يتم تطبيق ذلك؟

\n
    \n
  • حماية API من هجمات DDoS والبريد العشوائي.
  • \n
  • منع التحميل الزائد على الخادم عند الطلبات الجماعية.
  • \n
  • التحكم في استخدام الموارد في APIs المدفوعة (مثل 100 طلب في الساعة).
  • \n
  • الحماية من أخطاء "الحلقة اللانهائية" على العميل.
  • \n
\n\n

على عكس throttling الذي يعمل على تنعيم تدفق الطلبات، فإن rate limiting هو جدار صلب: "توقف، لقد تجاوزت الحد".

\n\n

Throttling مقابل Debounce: الفرق الرئيسي

\n\n

غالبًا ما يتم الخلط بين throttling و debounce. دعنا نوضح الأمور.

\n\n
    \n
  • Throttle — يضمن عدم استدعاء الدالة أكثر من مرة واحدة كل N ميلي ثانية. تخيل صنبور ماء: تفتحه، ويتدفق الماء بسرعة ثابتة، حتى لو قمت بتحريك المقبض بشكل أسرع.
  • \n
  • Debounce — يؤجل استدعاء الدالة حتى تمر N ميلي ثانية بعد آخر حدث. مثالي للبحث مع الإكمال التلقائي: أثناء كتابة المستخدم، لا يتم إرسال الطلب.
  • \n
\n\n

في سياق rate limiting، نحن مهتمون بـ throttle — نريد التحكم في التردد، وليس تأجيل الطلبات.

\n\n

أبسط rate limiter في JavaScript

\n\n

لنكتب تطبيقنا الخاص لـ rate limiter في Node.js. سيتذكر وقت آخر طلب من كل مستخدم ويمنع الطلبات المتكررة جدًا.

\n\n
class RateLimiter {\n  constructor(limit, windowMs) {\n    this.limit = limit;          // الحد الأقصى للطلبات\n    this.windowMs = windowMs;    // النافذة الزمنية بالميلي ثانية\n    this.requests = new Map();   // مخزن: userId -> [timestamps]\n  }\n\n  allow(userId) {\n    const now = Date.now();\n    const userRequests = this.requests.get(userId) || [];\n    \n    // حذف الإدخالات القديمة\n    const recentRequests = userRequests.filter(\n      ts => now - ts < this.windowMs\n    );\n    \n    if (recentRequests.length >= this.limit) {\n      console.log(`Rate limit exceeded for ${userId}`);\n      return false;\n    }\n    \n    recentRequests.push(now);\n    this.requests.set(userId, recentRequests);\n    return true;\n  }\n}\n\n// الاستخدام\nconst limiter = new RateLimiter(5, 60000); // 5 طلبات في الدقيقة\n\n// محاكاة الطلبات\nfor (let i = 0; i < 10; i++) {\n  setTimeout(() => {\n    const allowed = limiter.allow('user123');\n    console.log(`Request ${i+1}: ${allowed ? '✅ مسموح' : '❌ محظور'}`);\n  }, i * 2000); // كل ثانيتين\n}
\n\n

هذا الكود مناسب للأغراض التعليمية، ولكن في الإنتاج من الأفضل استخدام حلول جاهزة (مثل express-rate-limit لـ Express أو rate-limiter-flexible).

\n\n

Throttling على العميل: الحماية من النقرات السريعة

\n\n

غالبًا ما تنشأ المشكلة على جانب العميل: يضغط المستخدم على زر "إرسال" عدة مرات، وتُرسل الطلبات بشكل متوازٍ. ر

المدونات

توصيات الكتب