المستوى المطلوب: متوسط — لازم تكون عارف JavaScript بشكل أساسي، وفاهم Promises و callbacks، قبل ما تدخل في تفاصيل الـ Event Loop. لو لسه مبتدئ كليًا، ابدأ بمفهوم الـ Promise الأول وارجع للمقال ده بعدين.
لو setTimeout(fn, 0) بيشتغل بعد Promise.resolve().then(fn) رغم إن الاتنين كأنهم بصفر مللي ثانية، المشكلة مش في المتصفح ولا في الجهاز. ده تصميم مقصود في كل JavaScript runtime، وفهمه بيوفر عليك ساعات debug على bug ترتيب تنفيذ خفي.
Event Loop في JavaScript: ليه setTimeout(0) مش بصفر فعلاً؟
المشكلة باختصار
JavaScript لغة single-threaded — يعني خيط تنفيذ واحد فقط. لكن متصفحك بيقدر يعمل HTTP request وعداد ثواني وفي نفس اللحظة يستجيب لكليكاتك. الآلية اللي بتخلي ده ممكن اسمها Event Loop. ولو ما فهمتهاش، هتكتب كود "بيشتغل" لكن بترتيب مش اللي توقعته، وهتلاقي bugs بتظهر في production بس.
تشبيه للمبتدئ: المطعم اللي فيه طبّاخ واحد
تخيّل مطعم فيه طبّاخ واحد بس — ده الـ Call Stack، الخيط الوحيد اللي بينفّذ كود فعلاً. النادل بيستلم الطلبات الجديدة ويحطها على لوحتين مختلفتين على الحيطة:
- لوحة VIP: الطلبات اللي لازم تتعمل قبل أي حاجة تانية، حتى لو وصلت متأخر بعد طلبات عادية كتير.
- لوحة عادية: الطلبات بترتيب وصولها، الواحد ورا التاني.
الطبّاخ كل ما يخلص طبق، بيبص على لوحة VIP الأول. لو فاضية، بياخد طلب واحد بس من اللوحة العادية، بيخلصه، ثم يرجع يبص على VIP تاني. ده بالظبط الفرق بين Microtask Queue (لوحة VIP) و Macrotask Queue (اللوحة العادية) جوّا محرك V8.
التعريف العلمي الدقيق
الـ Event Loop آلية تنسيق بتشتغل في كل JavaScript runtime — المتصفح، Node.js، Deno، Bun. الدورة بسيطة لكن صارمة، وموثّقة في HTML Living Standard:
- نفّذ كل اللي على الـ Call Stack حتى يفضى.
- نفّذ كل الـ microtasks المتراكمة (مش واحدة، كلها لحد ما الطابور يفضى).
- ارسم الـ UI لو في تغييرات (في المتصفح فقط).
- اسحب مهمة واحدة فقط من macrotask queue ونفّذها، ثم ارجع للخطوة 1.
الفرق المحوري: microtasks بتتنفّذ كلها قبل أي macrotask تانية. ده يعني Promise.then دائمًا قبل setTimeout، حتى لو الـ setTimeout اتسجّل قبله بمسافة في الكود.