| المفهوم | الوظيفة |
|---|---|
| async function | دالة تُعيد Promise دائماً وتدعم await بداخلها |
| await | إيقاف تنفيذ الدالة حتى يستقر Promise معين |
| try...catch | التقاط أخطاء Promises المرفوضة داخل async |
async/await هي صيغة أُضيفت في ES2017 تجعل التعامل مع الكود غير المتزامن يبدو ويُقرأ تماماً كالكود المتزامن العادي (خطوة بخطوة بترتيب منطقي بسيط)، رغم أنها في الواقع مبنية بالكامل فوق Promises خلف الكواليس — وليست آلية جديدة كلياً، بل واجهة أنظف وأسهل قراءة لنفس المفهوم.
لتعريف دالة يمكنها استخدام await بداخلها، يجب وضع الكلمة المفتاحية async قبل تعريفها. أي دالة async تُعيد Promise تلقائياً دائماً، حتى لو كان الكود بداخلها يبدو أنه يُعيد قيمة عادية مباشرة — تُغلَّف تلك القيمة تلقائياً في Promise ناجح.
داخل دالة async فقط، يمكن استخدام await قبل أي تعبير يُعيد Promise — وهذا "يوقف" تنفيذ تلك الدالة تحديداً (وليس البرنامج بالكامل) حتى يستقر ذلك الـ Promise، ثم يستكمل التنفيذ بالقيمة التي حلَّ بها الوعد مباشرة، دون الحاجة لكتابة then() منفصلة. هذا يُنتج كوداً أفقياً واضحاً بدل تسلسل then().then().then() المتداخل.
للتعامل مع الأخطاء المحتملة (Promise مرفوض) داخل دالة async، تُستخدم try...catch التقليدية بدلاً من catch() — إذا رُفض أي await داخل try، يُرمى الخطأ ويُلتقط مباشرة في كتلة catch المقابلة، تماماً كما تتعامل مع أي استثناء (Exception) عادي في الكود المتزامن. هذا يوحّد طريقة معالجة الأخطاء بين الكود المتزامن وغير المتزامن.
| 1 | async function جلب_البيانات() { |
| 2 | try { |
| 3 | const استجابة = await fetch("https://api.example.com/data"); |
| 4 | const بيانات = await استجابة.json(); |
| 5 | console.log(بيانات); |
| 6 | return بيانات; |
| 7 | } catch (خطأ) { |
| 8 | console.error("حدث خطأ:", خطأ.message); |
| 9 | } |
| 10 | } |
مثال 1: async/await مقابل then التقليدية
| 1 | // مقارنة async/await مع then التقليدية لنفس المنطق |
| 2 | function تأخير(قيمة, مللي_ثانية) { |
| 3 | return new Promise(resolve => setTimeout(() => resolve(قيمة), مللي_ثانية)); |
| 4 | } |
| 5 | |
| 6 | // الطريقة القديمة مع then |
| 7 | تأخير(5, 500).then(رقم => { |
| 8 | تأخير(رقم * 2, 500).then(نتيجة => { |
| 9 | console.log("then:", نتيجة); |
| 10 | }); |
| 11 | }); |
| 12 | |
| 13 | // الطريقة الحديثة مع async/await — أوضح بكثير |
| 14 | async function احسب() { |
| 15 | const رقم = await تأخير(5, 500); |
| 16 | const نتيجة = await تأخير(رقم * 2, 500); |
| 17 | console.log("async/await:", نتيجة); |
| 18 | } |
| 19 | احسب(); |
مثال 2: تنفيذ متوازٍ داخل async/await باستخدام Promise.all
| 1 | // تنفيذ عدة عمليات غير متزامنة بالتوازي مع async/await |
| 2 | async function جلب_كل_البيانات() { |
| 3 | try { |
| 4 | const [مستخدمون, منتجات] = await Promise.all([ |
| 5 | fetch("/api/users").then(ر => ر.json()), |
| 6 | fetch("/api/products").then(ر => ر.json()), |
| 7 | ]); |
| 8 | console.log(مستخدمون, منتجات); |
| 9 | } catch (خطأ) { |
| 10 | console.error("فشل جلب البيانات:", خطأ.message); |
| 11 | } |
| 12 | } |