🟩 شرح Node.js

البنية وحلقة الأحداث

محرّك V8

Node.js مبني على محرّك V8 من جوجل — نفس المحرّك الذي يشغّل JavaScript في متصفّح Chrome. V8 يترجم JavaScript إلى لغة الآلة مباشرة، ما يجعله سريعًا جدًّا.

الفكرة العبقرية: أخذوا محرّك المتصفّح وشغّلوه على الخادم، فأصبح بإمكاننا كتابة الخلفية (Backend) بنفس لغة الواجهة.

البنية أحادية الخيط (Single-Threaded)

على عكس الخوادم التقليدية التي تفتح خيطًا (Thread) لكل طلب، يعمل Node على خيط واحد يخدم آلاف الطلبات. السرّ في عدم الحجب (Non-Blocking).

نموذج عدم الحجب (Non-Blocking I/O)

عندما يطلب الكود عملية بطيئة (قراءة ملف، استعلام قاعدة بيانات)، لا ينتظرها Node — بل يسجّلها ويكمل تنفيذ بقية الكود، ثم يعالج النتيجة عند جاهزيتها:

const fs = require("fs");

console.log("1 - قبل القراءة");

fs.readFile("file.txt", "utf-8", (err, data) => {
  console.log("3 - وصلت البيانات");
});

console.log("2 - بعد استدعاء القراءة");

// الترتيب: 1 ثم 2 ثم 3

لاحظ أن 2 طُبع قبل 3 رغم أن القراءة استُدعيت أولًا — لأن Node لم يحجب التنفيذ بانتظار الملف.

حلقة الأحداث (Event Loop)

هي قلب Node — حلقة لا نهائية تراقب المهام المنتهية وتنفّذ ردودها (callbacks). مبسّطًا:

  1. ينفّذ الكود المتزامن (synchronous) أولًا.
  2. يرسل العمليات البطيئة للنظام لتعمل في الخلفية.
  3. عند انتهائها، يضع ردودها في طابور.
  4. حلقة الأحداث تسحب من الطابور وتنفّذ الردود.
console.log("بداية");

setTimeout(() => console.log("مؤقّت"), 0);

Promise.resolve().then(() => console.log("وعد"));

console.log("نهاية");

// الترتيب: بداية، نهاية، وعد، مؤقّت

الوعود (microtasks) لها أولوية على المؤقّتات (macrotasks) — لذا "وعد" قبل "مؤقّت".

لماذا هذا مهم؟

  • Node ممتاز للتطبيقات كثيرة الإدخال/الإخراج (APIs، الدردشة، البث).
  • لكن العمليات الحسابية الثقيلة تحجب الخيط الوحيد — لها حلول لاحقة (Worker Threads).

أخطاء شائعة

  • توقّع تنفيذ الكود غير المتزامن بالترتيب الذي كُتب به.
  • تشغيل حسابات ثقيلة تحجب حلقة الأحداث فيتجمّد الخادم لكل المستخدمين.

🎯 التالي: سطر الأوامر وكائن process.