Asynchronous Programming

🧠 أولًا: ما المقصود بـ “تزامن”؟

“تزامن” هنا يعني: هل ينتظر البرنامج انتهاء العملية الحالية قبل تنفيذ العملية التالية؟

✅ البرمجة التزامنية (Synchronous Programming)
🔹 المفهوم:

هي الطريقة التقليدية في تنفيذ الأوامر، حيث يتم تنفيذ كل أمر واحدًا تلو الآخر، ولا يتم الانتقال للسطر التالي إلا بعد الانتهاء من السطر الحالي.

🔁 مثال واقعي:

أنت تقف في طابور في البنك. لا يتم خدمة الشخص التالي إلا بعد أن ينتهي الشخص الحالي.

📄 مثال برمجي (Dart):
print('1');
print('2');
print('3');
Dart

🔸 الناتج:

1
2
3
Dart

كل أمر ينتظر السابق أن ينتهي.

🔄 البرمجة غير التزامنية (Asynchronous Programming)
🔹 المفهوم:

يتم تنفيذ الأوامر بدون الانتظار، خاصة تلك التي تحتاج وقتًا طويلًا (مثل القراءة من الإنترنت أو القرص)، ويتم متابعة تنفيذ الكود دون توقف، ثم تُعاد النتيجة لاحقًا عندما تصبح جاهزة.

🔁 مثال واقعي:

أنت تطلب وجبة من مطعم. تطلب الوجبة وتذهب تجلس، ويأتيك النادل بها لاحقًا. لا تنتظر واقفًا.

📄 مثال برمجي (Dart) باستخدام Future:
void main() {
  print('1');

  Future.delayed(Duration(seconds: 2), () {
    print('2');
  });

  print('3');
}
Dart

🔸 الناتج:

1
3
2
Dart

لأن السطر الذي فيه Future.delayed ينتظر 2 ثانية، فيُكمل البرنامج تنفيذ السطر الذي بعده ثم يعود لطباعة “2” بعد التأخير.

🔧 لماذا نستخدم البرمجة غير التزامنية؟
📌 الأهمية:
  • تحسين الأداء: لا يتم تجميد التطبيق أثناء العمليات الثقيلة.
  • السلاسة في واجهة المستخدم: في تطبيقات مثل Flutter أو الويب، لا يتجمد التطبيق أثناء تحميل البيانات.
  • إدارة المهام المؤقتة: مثل الاتصال بالسيرفر، قراءة الملفات، استعلامات قواعد البيانات، إلخ.
⚙️ أدوات البرمجة غير التزامنية في Dart:
  • Future: نتيجة ستصل في المستقبل.
  • async/await: تسهّل كتابة الكود غير التزامني بطريقة تشبه التزامني.
  • Stream: للتعامل مع البيانات المتدفقة (مثل استقبال رسائل متعددة من API).
🎯 خلاصة سريعة:
المقارنةالتزامنية (Synchronous)غير التزامنية (Asynchronous)
التنفيذأمر بعد أمرقد تُكمل الأوامر في وقت لاحق
الأداءأبطأ في العمليات الثقيلةأسرع وأكثر تفاعلية
الاستخدام المناسبأوامر بسيطة وسريعةقراءة الملفات، الشبكة، انتظار المستخدم
🚀 ما هو Future؟

Future معناها عملية ستحدث في المستقبل وتستغرق بعض الوقت لتنتهي، مثل:

  • الانتظار لتحميل بيانات من الإنترنت.
  • قراءة ملف من الجهاز.
  • الانتظار لمدة معينة.

🔹 Dart لا “توقف” البرنامج، بل تتابع التنفيذ وتُكمل العملية لاحقًا.

✅ شكل Future في Dart
Future<int> getNumber() {
  return Future.delayed(Duration(seconds: 2), () => 10);
}
Dart
  • الدالة ترجع Future<int> → أي “قيمة صحيحة ستأتي لاحقًا“.
  • تستخدم Future.delayed لتأخير 2 ثانية.
✳️ الطريقة الأولى: باستخدام then()
void main() {
  print("Start");

  getNumber().then((value) {
    print("The number is $value");
  });

  print("End");
}

Future<int> getNumber() {
  return Future.delayed(Duration(seconds: 2), () => 10);
}
Dart

🔹 الناتج:

Start
End
The number is 10
Dart

✅ الكود يُكمل دون انتظار، ويطبع القيمة لاحقًا عندما تصل.

✳️ شرح ما يحدث:
1. print("Start");

يطبع مباشرة:

Start
Dart
2. getNumber().then((value) { ... });

هنا:

  • getNumber() تُعيد كائن Future يُكمل بعد تأخير مدته ثانيتين (Future.delayed).
  • عند اكتمال الـ Future، يتم استدعاء الكود داخل then() وتنفيذ الطباعة: csharpCopyEditThe number is 10

⚠️ لكنه لا ينتظر تنفيذ getNumber()، بل يذهب للسطر التالي مباشرة.

3. print("End");

يطبع مباشرة بعد Start لأن getNumber() لم تُنَفذ بعد (هي مؤجلة):

End
Dart
🔁 النتيجة الفعلية عند تشغيل البرنامج:
Start
End
The number is 10
Dart
🎯 ما فائدة then()؟

then() تستخدم للتعامل مع نتيجة الـ Future عندما تجهز.
هي وسيلة لربط كود معين يتم تشغيله بعد الانتهاء من العملية المؤجلة.

مثال واقعي:

Future<String> fetchUsername() {
  return Future.delayed(Duration(seconds: 2), () => "Yasin");
}

void main() {
  fetchUsername().then((username) {
    print("Welcome $username");
  });
}
Dart
❓ لماذا لا ينتظر Future؟

لأن Future يعمل بشكل لا تزامني (Asynchronous):

  • لا يوقف تنفيذ البرنامج.
  • يتيح تنفيذ التعليمات الأخرى ريثما يكتمل العمل المؤجل.
  • هذا يُفيد في عدم تجميد التطبيق، خصوصًا في تطبيقات الواجهات الرسومية أو الشبكات.
🔄 بديل then() — استخدام async و await:
Future<int> getNumber() {
  return Future.delayed(Duration(seconds: 2), () => 10);
}

void main() async {
  print("Start");

  int number = await getNumber(); // ينتظر حتى تجهز القيمة

  print("The number is $number");
  print("End");
}
Dart

💡 الناتج:

Start
The number is 10
End
Dart

هنا، await أوقفت التنفيذ مؤقتًا حتى تجهز القيمة.

✅ ملخص:
العنصرالوظيفة
Futureكائن يمثل عملية ستكتمل لاحقًا (مثلاً تحميل ملف أو بيانات من الإنترنت).
then()تُستخدم للتعامل مع القيمة بعد اكتمال الـ Future.
awaitتجعل البرنامج ينتظر القيمة بدلًا من المتابعة مباشرة.
asyncتوضع مع main أو أي دالة تحتوي await.
✳️ الطريقة الثانية: باستخدام async/await
void main() async {
  print("Start");

  int number = await getNumber();
  print("The number is $number");

  print("End");
}

Future<int> getNumber() {
  return Future.delayed(Duration(seconds: 2), () => 10);
}
Dart

🔹 الناتج:

Start
The number is 10
End
Dart

✅ عند استخدام await، ينتظر البرنامج النتيجة قبل أن يُكمل.

📌 متى نستخدم Future؟

عند التعامل مع أي شيء يأخذ وقتًا مثل:

  • جلب بيانات من الإنترنت.
  • الانتظار لرد من المستخدم.
  • الاتصال بقاعدة البيانات.
  • قراءة أو كتابة ملفات.
✅ مثال عملي: دالة ترجع رسالة بعد وقت
Future<String> fetchMessage() {
  return Future.delayed(Duration(seconds: 3), () => "تم تحميل الرسالة!");
}

void main() async {
  print("جاري التحميل...");
  String msg = await fetchMessage();
  print(msg);
}
Dart
✅ مثال: استخدام Future مع شرط
Future<String> checkLogin(String user, String pass) {
  return Future.delayed(Duration(seconds: 2), () {
    if (user == "admin" && pass == "1234") {
      return "تم تسجيل الدخول بنجاح";
    } else {
      return "فشل تسجيل الدخول";
    }
  });
}

void main() async {
  print("جارٍ تسجيل الدخول...");
  String result = await checkLogin("admin", "1234");
  print(result);
}
Dart
⚠️ التعامل مع الأخطاء في Future
باستخدام catchError:
Future<int> getError() {
  return Future.delayed(Duration(seconds: 1), () => throw "حدث خطأ");
}

void main() {
  getError().then((value) {
    print("النتيجة: $value");
  }).catchError((error) {
    print("الخطأ: $error");
  });
}
Dart
باستخدام try/catch مع async/await:
void main() async {
  try {
    int value = await getError();
    print("النتيجة: $value");
  } catch (e) {
    print("حدث خطأ: $e");
  }
}
Dart
🔄 الانتظار على أكثر من Future:
✅ Future.wait:
void main() async {
  List<Future<String>> tasks = [
    Future.delayed(Duration(seconds: 2), () => "مهمة 1"),
    Future.delayed(Duration(seconds: 1), () => "مهمة 2"),
  ];

  List<String> results = await Future.wait(tasks);
  print(results); // [مهمة 1, مهمة 2]
}
Dart
✅ تلخيص مهم
الكلمةمعناها
Future<T>قيمة ستعود من نوع T في المستقبل
awaitانتظر النتيجة قبل المتابعة
asyncاجعل الدالة تستطيع استخدام await
then()أسلوب لاستقبال النتيجة لاحقًا
catchError / try-catchللتعامل مع الأخطاء