الدرس الخامس والعشرون: العمل مع الـ Promises في JavaScript
في JavaScript، تُعد الـ Promises من المفاهيم الأساسية التي تتيح التعامل مع العمليات غير المتزامنة (Asynchronous operations) بطريقة أكثر مرونة وسهولة. هذا الدرس سيتناول كيفية إنشاء واستخدام الـ Promises، وكيفية التعامل مع نتائجها باستخدام then()، catch()، و finally، بالإضافة إلى كيفية تحسين التعامل معها باستخدام async/await.
1. ما هي الـ Promises؟
الـ Promise هي كائن يُستخدم لتمثيل العملية غير المتزامنة التي قد تُنجز في المستقبل. الـ Promise يمكن أن يكون في أحد الحالات التالية:
- Pending: عندما تكون العملية غير متكاملة بعد.
- Resolved أو Fulfilled: عندما يتم الانتهاء من العملية بنجاح.
- Rejected: عندما تفشل العملية.
تُستخدم الـ Promises لتجنب استخدام callbacks المعقدة في التعامل مع العمليات غير المتزامنة، وتوفر طريقة أكثر وضوحًا للتعامل مع النجاح أو الفشل.
2. كيفية إنشاء واستخدام الـ Promises
يمكن إنشاء Promise باستخدام الكلمة المفتاحية new Promise()، والتي تتطلب دالة تحتوي على معالجتين:
- resolve(): تُستدعى عندما يتم إتمام العملية بنجاح.
- reject(): تُستدعى عندما تفشل العملية.
مثال على إنشاء واستخدام Promise:
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("العملية تمت بنجاح");
} else {
reject("حدث خطأ أثناء العملية");
}
});
// التعامل مع Promise باستخدام then() و catch()
myPromise
.then((result) => {
console.log(result); // "العملية تمت بنجاح"
})
.catch((error) => {
console.log(error); // "حدث خطأ أثناء العملية"
});
3. التعامل مع نتائج الـ Promise باستخدام then() و catch() و finally
then():
تُستخدم then() لمعالجة النتائج عندما يتم إتمام الـ Promise بنجاح (أي عندما يتم استدعاء resolve()).
catch():
تُستخدم catch() لمعالجة الأخطاء أو الفشل، عندما يتم استدعاء reject().
finally:
تُستخدم finally() لتنفيذ الكود بغض النظر عن نجاح أو فشل الـ Promise. يمكن استخدامها لتنظيف الموارد أو إتمام عمليات مهما كانت النتيجة.
مثال على استخدام then() و catch() و finally:
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("العملية تمت بنجاح");
} else {
reject("حدث خطأ أثناء العملية");
}
});
myPromise
.then((result) => {
console.log(result); // "العملية تمت بنجاح"
})
.catch((error) => {
console.log(error); // "حدث خطأ أثناء العملية"
})
.finally(() => {
console.log("تم الانتهاء من المعالجة، سواء نجحت أو فشلت"); // سيتم تنفيذه دائمًا
});
4. تحسين التعامل مع الـ Promises باستخدام async/await
على الرغم من أن then() و catch() طريقة فعالة للتعامل مع الـ Promises، إلا أن async/await يوفر طريقة أكثر وضوحًا وقراءة لتنفيذ العمليات غير المتزامنة. تم تقديم async/await في ECMAScript 2017، وتتيح لك كتابة الكود بشكل متسلسل يشبه الكود المتزامن (synchronous) مع الحفاظ على المعالجة غير المتزامنة.
- async: تُستخدم قبل تعريف دالة لجعلها دالة غير متزامنة.
- await: تُستخدم داخل الدوال غير المتزامنة لانتظار الـ Promise حتى يتم حلها أو رفضها.
مثال على استخدام async/await:
// تعريف دالة غير متزامنة
async function processData() {
try {
const result = await myPromise; // ننتظر إتمام الـ Promise
console.log(result); // "العملية تمت بنجاح"
} catch (error) {
console.log(error); // "حدث خطأ أثناء العملية"
} finally {
console.log("تم الانتهاء من المعالجة");
}
}
const myPromise = new Promise((resolve, reject) => {
let success = true;
if (success) {
resolve("العملية تمت بنجاح");
} else {
reject("حدث خطأ أثناء العملية");
}
});
processData(); // تنفيذ الدالة
في هذا المثال:
- await يجعلنا ننتظر حل الـ Promise قبل المضي قدمًا.
- try/catch يُستخدم لمعالجة الأخطاء بطريقة مشابهة للتعامل مع الكود المتزامن.
- finally تُستخدم لتنفيذ الكود في النهاية بغض النظر عن النتيجة.
5. الانتظار لعدة Promises باستخدام Promise.all() و Promise.allSettled()
في بعض الأحيان، قد تحتاج إلى التعامل مع عدة Promises في نفس الوقت. يمكن استخدام Promise.all() أو Promise.allSettled() لتحقيق ذلك.
Promise.all():
تنتظر حتى يتم حل جميع الـ Promises المُعطاة. إذا فشل أي Promise، فسيتم رفض الكل.
const promise1 = new Promise((resolve) => resolve("العملية 1"));
const promise2 = new Promise((resolve) => resolve("العملية 2"));
const promise3 = new Promise((resolve) => resolve("العملية 3"));
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results); // ["العملية 1", "العملية 2", "العملية 3"]
})
.catch((error) => {
console.log(error); // سيتم تنفيذه إذا فشل أي Promise
});
Promise.allSettled():
تنتظر حتى يتم حل جميع الـ Promises سواء كانت ناجحة أو فاشلة. هذه الطريقة مفيدة عندما ترغب في معرفة نتيجة كل Promise بغض النظر عن نجاحها أو فشلها.
const promise1 = new Promise((resolve) => resolve("العملية 1"));
const promise2 = new Promise((reject) => reject("خطأ في العملية 2"));
const promise3 = new Promise((resolve) => resolve("العملية 3"));
Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
console.log(results);
/*
[
{ status: 'fulfilled', value: 'العملية 1' },
{ status: 'rejected', reason: 'خطأ في العملية 2' },
{ status: 'fulfilled', value: 'العملية 3' }
]
*/
});
الخلاصة
- Promises هي طريقة للتعامل مع العمليات غير المتزامنة في JavaScript وتوفير طرق أكثر مرونة لكتابة الكود.
- then() و catch() و finally تُستخدم للتعامل مع نتائج الـ Promise وإدارة الأخطاء وتنفيذ الكود بعد العملية.
- async/await توفر طريقة أكثر بساطة ووضوحًا للتعامل مع الـ Promises بشكل متسلسل.
- Promise.all() و Promise.allSettled() تُستخدم لتنفيذ العديد من الـ Promises في نفس الوقت والتعامل مع نتائجها.
الـ Promises و async/await هما الأدوات الرئيسية في JavaScript للتعامل مع العمليات غير المتزامنة، مما يسهل الكتابة والقراءة والصيانة للكود الخاص بالتطبيقات الحديثة.
اكتشاف المزيد من كود التطور
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.


