البرمجة غير المتزامنة في TypeScript: دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

البرمجة غير المتزامنة في TypeScript: دليل شامل للمبتدئين

\n\n

البرمجة غير المتزامنة هي أحد المفاهيم الأساسية في تطوير الويب الحديث. إذا كنت قد بدأت للتو في تعلم TypeScript، فإن فهم كيفية العمل مع الكود غير المتزامن سيفتح أمامك إمكانيات لإنشاء تطبيقات سريعة وسريعة الاستجابة. في هذا الدليل، سنشرح أساسيات البرمجة غير المتزامنة في TypeScript: من الاستدعاءات البسيطة (callbacks) إلى async/await الحديثة، مع التركيز على الكتابة الصارمة للأنواع التي يوفرها TypeScript.

\n\n

ما هي البرمجة غير المتزامنة ولماذا نحتاجها؟

\n\n

في البرمجة المتزامنة، يتم تنفيذ الكود بشكل تسلسلي: كل عملية تالية تنتظر انتهاء العملية السابقة. قد يؤدي ذلك إلى "تجميد" الواجهة إذا كنت بحاجة، على سبيل المثال، إلى تحميل بيانات من الخادم. تسمح البرمجة غير المتزامنة بتشغيل العمليات الطويلة (طلبات API، قراءة الملفات، المؤقتات) في الخلفية، دون حظر تيار التنفيذ الرئيسي. TypeScript، كونه امتدادًا لـ JavaScript، يدعم بشكل كامل الأنماط غير المتزامنة ويضيف إليها نظام أنواع قوي.

\n\n

Promise: أساس البرمجة غير المتزامنة في TypeScript

\n\n

Promise هو كائن يمثل نتيجة عملية غير متزامنة، ويمكن أن يكون في إحدى ثلاث حالات: pending (قيد الانتظار)، fulfilled (تم التنفيذ بنجاح) أو rejected (تم التنفيذ مع خطأ). في TypeScript، يمكننا تحديد نوع البيانات التي سيعيدها الـ Promise، مما يجعل الكود أكثر قابلية للتنبؤ.

\n\n

مثال على إنشاء Promise مع كتابة الأنواع:

\n\n
// دالة تعيد Promise من نوع string\nfunction fetchUserData(userId: number): Promise<string> {\n    return new Promise((resolve, reject) => {\n        setTimeout(() => {\n            if (userId > 0) {\n                resolve(`بيانات المستخدم بالمعرف ${userId}`);\n            } else {\n                reject(new Error("معرف مستخدم غير صحيح"));\n            }\n        }, 1000);\n    });\n}\n\n// استخدام Promise\nfetchUserData(123)\n    .then((data: string) => {\n        console.log(data); // "بيانات المستخدم بالمعرف 123"\n    })\n    .catch((error: Error) => {\n        console.error(error.message);\n    });
\n\n

لاحظ: لقد حددنا بوضوح أن الـ Promise يعيد string، وفي .then() المعامل data له أيضًا النوع string. يساعد هذا في تجنب الأخطاء في مرحلة التجميع.

\n\n

سلاسل Promise ومعالجة الأخطاء

\n\n

يمكن ربط الـ Promises في سلاسل، لنقل نتيجة عملية غير متزامنة إلى أخرى. سيقوم TypeScript تلقائيًا باستنتاج الأنواع في كل خطوة.

\n\n

مثال على سلسلة Promise:

\n\n
interface User {\n    id: number;\n    name: string;\n}\n\nfunction getUser(id: number): Promise<User> {\n    return new Promise((resolve) => {\n        setTimeout(() => resolve({ id, name: "آنا" }), 500);\n    });\n}\n\nfunction getPosts(userId: number): Promise<string[]> {\n    return new Promise((resolve) => {\n        setTimeout(() => resolve(["منشور 1", "منشور 2"]), 500);\n    });\n}\n\n// سلسلة الاستدعاءات\ngetUser(1)\n    .then((user: User) => {\n        console.log(`المستخدم: ${user.name}`);\n        return getPosts(user.id); // نعيد Promise جديد\n    })\n    .then((posts: string[]) => {\n        console.log(`المنشورات: ${posts.join(", ")}`);\n    })\n    .catch((error: Error) => {\n        console.error("خطأ:", error.message);\n    });
\n\n

إذا حدث خطأ في أي مرحلة، سينتقل التنفيذ إلى أقرب .catch(). هذه معالجة مركزية للأخطاء - وهي إحدى المزايا الرئيسية للـ Promises مقارنة بالاستدعاءات (callbacks).

\n\n

Async/await: بناء جملة أنيق للبرمجة غير المتزامنة

\n\n

بناء جملة async/await يجعل الكود غير المتزامن يبدو وكأنه متزامن، مما يبسط قراءته

المدونات

توصيات الكتب