✅ أولاً: ما معنى Synchronous و Asynchronous؟
🔹 Synchronous Programming (البرمجة المتزامنة)
- تعني أن كل سطر من الكود يتم تنفيذه بعد الانتهاء من السطر السابق.
- JavaScript افتراضيًا لغة Single-threaded (تعمل بسلسلة تنفيذ واحدة)، مما يعني أنها تنفذ الكود سطرًا تلو الآخر.
في JavaScript، عندما نقول إن اللغة Single-threaded “أحادية الخيط”، فإن ذلك يعني:
JavaScript تنفذ التعليمات واحدة تلو الأخرى في تسلسل، على مسار واحد فقط (خيط واحد – Thread).
ما المقصود بـ “Thread”؟
الخيط (Thread) هو المسار الذي تسير فيه التعليمات داخل المعالج. بعض اللغات مثل Java أو C++ يمكنها تشغيل أكثر من خيط في نفس الوقت (Multithreading)، ولكن JavaScript لا تفعل ذلك بشكل مباشر.
لماذا JavaScript مصممة بهذه الطريقة؟
JavaScript صُممت أساسًا لتشغيل الكود داخل المتصفحات، ولا سيما للتفاعل مع واجهة المستخدم (UI). لو كانت متعددة الخيوط (Multithreaded)، قد يتسبب هذا في تعقيد كبير وتضارب عند التفاعل مع العناصر في الصفحة.
ماذا يعني هذا للمطورين؟
- لا يمكن تنفيذ أكثر من مهمة في نفس اللحظة داخل JavaScript.
- إذا كانت هناك عملية بطيئة (مثل جلب بيانات من الإنترنت أو قراءة ملف كبير)، فإنها قد تعطل باقي التعليمات إذا لم تتم إدارتها بطريقة غير متزامنة (asynchronous).
كيف تتعامل JavaScript مع المهام الطويلة؟
رغم أنها Single-threaded، إلا أن JavaScript تدعم آليات غير متزامنة (Asynchronous) مثل:
setTimeout
Promises
async/await
- Web APIs (مثل
fetch
) - Event Loop
هذه الأدوات تمنح وهم التعدد (pseudo-concurrency) من خلال تفويض المهام الطويلة إلى Web APIs خارج الخيط الأساسي، ثم تعيد نتائجها لاحقًا دون حجز الخيط.
ملخص:
Single-threaded تعني أن JavaScript تنفذ كودًا واحدًا في وقت واحد، لكن يمكنها التعامل مع المهام الطويلة بطريقة ذكية باستخدام آليات غير متزامنة.
🧠 مثال:
console.log("1");
console.log("2");
alert("test");
console.log("3");
////////////////////////////////
1
2
3
JavaScriptيتم تنفيذ الأوامر بالترتيب، وكل أمر ينتظر السابق حتى ينتهي.
🔹 Asynchronous Programming (البرمجة غير المتزامنة)
- تسمح بتنفيذ بعض الأوامر بشكل غير متزامن، أي لا تنتظر تنفيذ الأوامر الأخرى.
- تُستخدم لتحسين الأداء عند التعامل مع عمليات تستغرق وقتًا (مثل: طلب بيانات من API، أو قراءة ملفات).
✅ أمثلة عملية
📌 مثال على Asynchronous باستخدام setTimeout
console.log("1");
setTimeout(() => {
console.log("2");
}, 2000); // ينتظر ثانيتين
console.log("3")
/////////////////////////
1
3
2
JavaScript🧠 الشرح:
- يتم تنفيذ
1
. - ثم يتم جدولة
2
ليتم تنفيذه بعد ثانيتين. - يتم تنفيذ
3
مباشرة دون انتظار2
. - بعد ثانيتين، يُنفذ الكود داخل
setTimeout
.
✅ كيف تدير JavaScript العمليات غير المتزامنة؟
JavaScript تستخدم ما يُعرف بـ Event Loop:
- تنفذ الـ Call Stack الأوامر المتزامنة.
- الأوامر غير المتزامنة تُرسل إلى Web APIs (مثل
setTimeout
,fetch
). - عند الانتهاء، تُرسل إلى Callback Queue.
- عندما تصبح الـ Call Stack فارغة، ينقل الـ Event Loop الأوامر من الـ Callback Queue لتنفيذها.
✅ Promises (الوعود) – طريقة حديثة للتعامل مع Asynchronous
📌 مثال باستخدام Promise:
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("تمت العملية!");
}, 2000);
});
promise.then(result => {
console.log(result); // "تمت العملية!" بعد ثانيتين
});
JavaScript✅ Async / Await – أسلوب حديث مبني على Promises لكتابة كود يبدو متزامنًا لكنه غير متزامن
function getData() {
return new Promise(resolve => {
setTimeout(() => {
resolve("البيانات جاهزة");
}, 2000);
});
}
async function showData() {
console.log("1");
let result = await getData(); // ينتظر حتى يتم حل الـ Promise
console.log(result); // "البيانات جاهزة"
console.log("3");
}
showData();
JavaScript1
(انتظار ثانيتين)
البيانات جاهزة
3
JavaScript✅ الفرق الجوهري
الخاصية | Synchronous | Asynchronous |
---|---|---|
الترتيب | تنفيذي صارم | يمكن تجاوز بعض الأوامر |
الأداء | بطيء مع العمليات الثقيلة | سريع ومناسب للعمليات المؤجلة |
الاستخدام | الأوامر البسيطة | API, ملفات, عمليات معقدة |
التعامل | مباشر | يستخدم Callbacks / Promises / Async-Await |
✅ خلاصة:
- البرمجة المتزامنة: تنفذ الأوامر واحدًا تلو الآخر.
- البرمجة غير المتزامنة: تسمح بتنفيذ أوامر دون انتظار أوامر أخرى.
- JavaScript تستخدم أساليب مثل:
setTimeout
,fetch
,Promise
, وasync/await
للتعامل مع البرمجة غير المتزامنة.
ما هو الـ Call Stack؟
✅ تعريف:
الـ Call Stack (مكدس الاستدعاء) هو المكان الذي تُسجّل فيه JavaScript جميع الدوال التي يجب تنفيذها.
هو عبارة عن مكدّس (Stack) يعمل بطريقة LIFO (آخر من يدخل هو أول من يخرج).

🧠 كيف يعمل؟
عند استدعاء دالة:
- تُضاف إلى الـ Call Stack.
- تُنفذ الدالة.
- بعد انتهاء التنفيذ، تُزال من الـ Stack.
📌 مثال:
function greet() {
console.log("Hello!");
}
function start() {
greet();
}
start();
JavaScript🔁 خطوات التنفيذ في الـ Call Stack:
start()
تدخل إلى الـ Stack- داخل
start()
, يتم استدعاءgreet()
greet()
تدخل إلى الـ Stackconsole.log("Hello!")
ينفذgreet()
تنتهي وتخرج من الـ Stackstart()
تنتهي وتخرج من الـ Stack
function first() {
console.log("1: First function");
second();
console.log("1: Back to First function");
}
function second() {
console.log("2: Second function");
third();
console.log("2: Back to Second function");
}
function third() {
console.log("3: Third function");
}
first();
JavaScript✅ ما الذي يحدث داخل الـ Call Stack خطوة بخطوة؟
- يتم استدعاء
first()
→ تدخل إلى الـ Stack. - تطبع:
1: First function
- تستدعي
second()
→ تدخل فوقfirst()
في الـ Stack. - تطبع:
2: Second function
- تستدعي
third()
→ تدخل فوقsecond()
في الـ Stack. - تطبع:
3: Third function
- تنتهي
third()
→ تخرج أولًا من الـ Stack (لأنها آخر من دخل). - نعود إلى
second()
وتُكمل: تطبع2: Back to Second function
→ ثم تخرج. - نعود إلى
first()
وتُكمل: تطبع1: Back to First function
→ ثم تخرج.
🔷ما هي الـ Web API؟
✅ تعريف:
الـ Web API هي مجموعة من الوظائف التي توفرها المتصفح (وليس JavaScript نفسها)، وتُستخدم للقيام بمهام مثل:
setTimeout
fetch
- التعامل مع DOM
- الأحداث
addEventListener
JavaScript نفسها لا تملك
setTimeout
– بل هي وظيفة مقدمة من Web APIs في المتصفح.
🧠 كيف تعمل Web API مع Call Stack؟
دعنا نأخذ مثالًا توضيحيًا 👇
📌 مثال:
console.log("1");
setTimeout(() => {
console.log("2");
}, 2000);
console.log("3");
JavaScript✅ ماذا يحدث وراء الكواليس؟
console.log("1")
→ تدخل إلى Call Stack → تنفذ → تخرجsetTimeout(...)
→ تدخل إلى Call Stack → يُرسل الـ callback إلى Web API → تخرجconsole.log("3")
→ تدخل إلى Call Stack → تنفذ → تخرج- بعد 2 ثانية، تنتهي Web API من المؤقت → ترسل الـ callback (
() => console.log("2")
) إلى Callback Queue - الـ Event Loop يلاحظ أن الـ Call Stack فارغ → ينقل الدالة من Callback Queue إلى Call Stack
console.log("2")
→ تنفذ وتخرج
🔄 التخطيط الزمني:
Call Stack: | console.log("1") | setTimeout(...) | console.log("3") | () => console.log("2")
Web API: | -- | timer runs | -- | --
Callback Queue: | -- | -- | -- | () => console.log("2")
Event Loop: | ينقل callback من الـ queue عندما يكون Call Stack فارغًا
JavaScript🖼️ رسم توضيحي مبسط:
[ Call Stack ]
| |
| console.log(2) ← Event Loop ينقلها من Callback Queue
|_____________|
[ Callback Queue ]
| () => console.log("2") |
[ Web APIs ]
| setTimeout running... |
[ Event Loop ]
👁️ يراقب Call Stack وينقل الدوال الجاهزة من Callback Queue
JavaScript✅ خلاصة:
المكون | الوظيفة |
---|---|
Call Stack | ينفذ الكود سطرًا بسطر (المتزامن) |
Web APIs | تدير العمليات غير المتزامنة مثل setTimeout و fetch |
Callback Queue | تنتظر فيها الدوال غير المتزامنة لحين تنفيذها |
Event Loop | ينقل الدوال الجاهزة من Queue إلى Stack |
🔷 ما هو Event Loop؟
✅ تعريف:
الـ Event Loop هو الآلية التي تسمح لـ JavaScript (التي تعمل بشكل متزامن Single-threaded) بأن تدير عمليات غير متزامنة بكفاءة، مثل:
setTimeout
fetch
- أحداث
click
- Promises
🔷 ما هي Callback Queue؟
✅ تعريف:
الـ Callback Queue (طابور الاستدعاءات الراجعة) هي المكان الذي تنتظر فيه الدوال (Callbacks) التي تأتي من Web APIs بعد انتهاء تنفيذها، حتى يسمح لها الـ Event Loop بالدخول إلى Call Stack وتنفيذها.
🔁 كيف يعمل النظام كاملًا؟ (بترتيب الخطوات)
تخيل الكود التالي:
console.log("1");
setTimeout(() => {
console.log("2");
}, 2000);
console.log("3");
JavaScript🔄 خطوات التنفيذ:
console.log("1")
→ يُنفذ مباشرة داخل الـ Call Stack.setTimeout(...)
→ يُمرر إلى Web API الخاصة بالمتصفح، ويبدأ العداد (2 ثانية).console.log("3")
→ يُنفذ مباشرة بعدsetTimeout
.- بعد مرور ثانيتين:
- يُنقل الـ
() => console.log("2")
إلى Callback Queue.
- يُنقل الـ
- الـ Event Loop يراقب الـ Call Stack، وبمجرد أن يكون فارغًا:
- ينقل الدالة من Callback Queue إلى Call Stack لتنفيذها.
🖼️ تصور بصري للحركة
1. Call Stack: console.log("1") → يُنفذ
2. Web API: setTimeout → يبدأ العداد
3. Call Stack: console.log("3") → يُنفذ
4. بعد 2 ثانية:
- Web API تنقل () => console.log("2") إلى Callback Queue
5. Event Loop: يلاحظ أن Call Stack فارغ → ينقل () => console.log("2") لتنفيذه
JavaScript✅ ملخص المكونات الرئيسية:
المكون | الوظيفة |
---|---|
Call Stack | ينفذ الأوامر واحدًا تلو الآخر |
Web APIs | تدير العمليات غير المتزامنة (مثل timers و fetch و DOM events) |
Callback Queue | تخزن الدوال الراجعة callbacks المنتظرة ليتم تنفيذها لاحقًا |
Event Loop | ينقل الـ callbacks من الـ Callback Queue إلى Call Stack عند الفراغ |
📌 مثال عملي أكثر تعقيدًا:
console.log("Start");
setTimeout(() => {
console.log("Timeout");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("End");
JavaScriptStart
End
Promise
Timeout
JavaScript❓ لماذا؟
console.log("Start")
→ يُنفذsetTimeout(..., 0)
→ يُرسل إلى Web API، وتنتقل الدالة إلى Callback QueuePromise.then(...)
→ يُرسل إلى Microtask Queueconsole.log("End")
→ يُنفذ- بعد الانتهاء من Call Stack، يُفضل الـ Event Loop Microtask Queue (مثل Promise) قبل Callback Queue.
- ثم ينفذ الكود داخل
then()
- وأخيرًا، ينفذ الدالة داخل
setTimeout
✅ Microtask Queue vs Callback Queue
النوع | الاستخدام | أولوية التنفيذ |
---|---|---|
Callback Queue | setTimeout, DOM events | أقل أولوية |
Microtask Queue | Promises, async/await | أعلى أولوية، تُنفذ قبل الـ Callbacks |
🎯 خلاصة:
- الـ Event Loop هو القلب النابض الذي ينسق بين Call Stack و Web APIs و Queues.
- عندما ينتهي تنفيذ المهام المتزامنة، يبدأ Event Loop في إدخال المهام غير المتزامنة (callbacks) من الطوابير.
- Promises (Microtasks) دائمًا تُنفذ قبل setTimeout (Callbacks) إذا كانت جاهزة.