فهم الـ Node.js Event Loop
الـ Event Loop ليس عاملاً، بل هو منسق.
يجد العديد من المطورين أن الـ Event Loop معقد. وغالباً ما ينبع هذا التعقيد من خلط الكثير من المفاهيم في وقت واحد؛ حيث يتعين عليك تتبع libuv، والـ Call Stack، والـ Promises، والـ I/O جميعها في آن واحد.
إليك الحقيقة البسيطة: الـ Event Loop يقوم بجدولة العمل، ولا يقوم بالعمل نفسه.
تعمل JavaScript على مسار تنفيذ واحد (single thread). وهذا يعني أن الكود يعمل في خط مستقيم؛ حيث يجب أن تنتهي مهمة واحدة قبل أن تبدأ المهمة التالية. لذا، نحتاج إلى نظام لإدارة المهام غير المتزامنة (asynchronous tasks) مثل قراءة الملفات أو طلبات الشبكة دون إيقاف البرنامج بأكمله.
كيف يعمل:
يقوم الـ Event Loop بنقل الـ callbacks من طوابير (queues) مختلفة إلى الـ Call Stack. تخيل كل مرحلة كأنها طابور، والـ Event Loop هو الشخص الذي ينقل الناس من الطابور إلى الغرفة.
المراحل الرئيسية هي:
- Timers: تتعامل مع الـ callbacks من setTimeout و setInterval.
- Pending Callbacks: تتعامل مع أخطاء نظام محددة مثل أخطاء TCP.
- Idle and Prepare: مراحل داخلية يستخدمها libuv، ولن تستخدمها أنت.
- Poll: المرحلة الأكثر أهمية، حيث تقوم باسترداد أحداث I/O جديدة مثل قراءة الملفات أو طلبات HTTP.
- Check: تتعامل مع الـ callbacks الخاصة بـ setImmediate.
- Close Callbacks: تتعامل مع أحداث الإغلاق مثل إغلاق الـ socket.
من الأخطاء الشائعة الاعتقاد بأن للـ Event Loop الـ Call Stack الخاص به. لكن هذا غير صحيح؛ فبيئة التشغيل (runtime) تمتلك Call Stack واحد فقط وطابور microtask واحد.
تتبع العملية هذا التدفق:
- يقوم الـ Event Loop باختيار callback من المرحلة الحالية.
- يقوم بدفع (push) ذلك الـ callback إلى الـ Call Stack.
- يقوم الـ Call Stack بتنفيذ الكود.
- بمجرد انتهاء الـ callback، يقوم المحرك بتفريغ الـ microtask queue. وهنا تكمن الـ Promises والـ async/await.
- ينتقل الـ Event Loop إلى المرحلة التالية.
إذا استخدمت setTimeout(..., 0)، فسيذهب إلى مرحلة الـ Timers. إذا استخدمت setImmediate(...), فسيذهب إلى مرحلة الـ Check.
العمل الشاق يحدث في الـ OS kernel و libuv. أما الـ Event Loop فيقوم ببساطة بإخبار JavaScript متى يحين وقت الاستجابة.
المصدر: https://dev.to/joaovictor6/event-loop-entendendo-uma-das-bases-do-node-41a