Node.js'te event loop nedir ve nasıl çalıştığını merak ediyorum. Tek iş parçacığı üzerinde aynı anda birden fazla isteği nasıl yönetebildiğini, callback kuyruğu, microtask ve makrotask kavramlarını örneklerle açıklarsanız çok sevinirim. Sizin deneyimlerinizde bu mekanizma performansı nasıl etkiliyor? Ayrıca, bloklama yapan kodların loop üzerindeki etkisini ve bunun önüne geçmek için kullanılabilecek yöntemleri de öğrenmek istiyorum.
Node.js Event Loop Nasıl Çalışır? İş Parçacığı ve Görev Yönetimi
👁️ 74 görüntüleme💬 2 cevap❤️ 0 beğeni
2 Cevap
صحيح، عندما استخدمت `setTimeout` مع `process.nextTick` لاحظت أن الـmicrotask مثل `Promise.then` يُنفذ قبل الـmacrotask، لذا طلبات الـIO لا تنتظر غيرها وتستمر في التدفق؛ أما الكود الحاجز مثل `while(true){}` فإنه يوقف الـevent loop تماماً، لذا أنصح باستخدام `async/await` مع `fs.promises` أو نقل العمليات الثقيلة إلى Worker Threads لتفادي تجميد الخادم.
في Node.js يتم تشغيل الـ Event Loop على خيط واحد يقرأ من طابور الأحداث ويعالج كل دور (tick) بالترتيب التالي: macrotasks (مثل I/O callbacks, timers) ثم microtasks (Promise‑then، process.nextTick). عندما يكتمل الـ macrotask، ينتقل اللوب مباشرةً إلى جميع الـ microtasks المعلقة قبل أن يبدأ الدور التالي. هذا يعني أن أي Promise.resolve().then() سيُنفّذ قبل أي مؤقت يوقت بـ setTimeout 0 مل ، وبالتالي يسرّع من معالجة النتائج غير المتزامنة.
في تجاربي، عندما أضع عمليات I/O ثقيلة أو عمليات حسابية معقدة داخل الـ callback مباشرةً، يظل الـ Event Loop محجوزًا لفترة طويلة ويؤدي ذلك إلى زيادة زمن الاستجابة وتراكم الطلبات. لتفادي ذلك، أقوم بتحويل القَصَص الحسابية إلى workers (thread pool) عبر worker_threads أو أستخدم مكتبة Bull/Redis للمعالجة غير المتزامنة، وأحافظ على أن جميع الـ callbacks تكون غير محبطة (non‑blocking). مثال عملي: استبدلت حلقة for تُجري ملايين القيم بعملية Promise.all مع تنفيذ جزئي داخل worker_thread، وفورًا لاحظت انخفاضًا في زمن الـ latency من عدة مئات مل إلى أقل من 30 مل .
بالنسبة للـ microtasks، أُفضِّل دائماً أن أضع منطق الأعمال التي يجب أن تُنفذ فورًا بعد استكمال الـ macrotask في .then() أو process.nextTick بدلاً من إدراجها داخل الـ callback الرئيسي، لأن ذلك يضمن أن الـ Event Loop لا ينتظر أية عملية I/O غير مكتملة قبل إكمال الدورة. لكن يجب الحذر من إنشاء سلسلة غير محدودة من الـ microtasks، حيث قد يستهلك ذلك كل دورة ويمنع الانتقال إلى الـ macrotasks، ما يسبب “starvation”.
خلاصةً: حافظ على أن تكون كل الدوال في الـ Event Loop غير محجبة، استخدم workers أو أدوات queue للمهام الثقيلة، واحرص على توزيع الـ microtasks بحكمة لتجنب حجب الـ macrotasks. بهذه الطريقة يظل التطبيق سريعًا ومستقرًا حتى تحت ضغط عالي من الطلبات.