لا تحاول فرض async/await
الوعود هي الموضة الآن
منذ بداية الزمن، خاض المطورون العديد من المعارك السخيفة. من الجدل الكلاسيكي “المسافات البادئة مقابل المسافات” إلى النقاش الخالد _“ماك مقابل بي سي”، نحن بارعون في إيجاد حجج مشتتة للانتباه.
الإجابات: لينكس والمسافات.
المعركة…؟
الوعود (Promises) مقابل Async/Await!
لحظة، هل هذه معركة؟ لا بد أنها كذلك، أليس كذلك؟ يبدو أننا لم نعد نتحدث عن دوال الاسترجاع (callbacks) بعد الآن؟
لا، إنها ليست معركة. في النهاية، إنها أداة أخرى محتملة في صندوق أدواتك. ومع ذلك، لأن async/await لا تحل محل كل وظائف الوعود (تحديدًا Promise.all، .race) فإن تقديمها كبديل هو أمر مضلل.
هناك الكثير من الأشخاص المؤثرين الذين يروجون لهذا المفهوم الخاطئ بأن async/await هي البديل الذي كان الجميع ينتظره للوعود.
تلميح: لا، كلا، ولا حتى قليلاً.
إضافة حديثة إلى VS Code تعزز هذا التحيز. كما غرد @umaar:
يمكن لـ Visual Studio Code الآن تحويل سلاسل Promise.then() الطويلة إلى async/await! 🎊 تعمل بشكل جيد في ملفات JavaScript و TypeScript. كما يتم تحويل .catch() بشكل صحيح إلى try/catch ✅ pic.x.com/xb39Lsp84V
— عمر هانزا (@umaar) 28 سبتمبر 2018
إذا كنت تكره الوعود، وتريد هذه الميزة لإعادة الهيكلة، فلا ألومك.
أتعاطف معك. أفهمك.
لقد كنت في مكانك. 🤗
كنت أكره الوعود سابقًا. اليوم، عدت تمامًا إلى صوابي. الوعود رائعة. فهي تمكنك/تشجعك على الاستفادة من تركيب الدوال.
هناك مجالان أوصي بالتركيز عليهما أولاً لتطوير أسلوبك مع الوعود.
#1: الدوال المسماة!
تخلَّص من دوالك المجهولة. استخدام الدوال المسماة يجعل الكود يقرأ كشعر يعبّر عن متطلباتك.
لننظر إلى مثال شائع:
إجراء طلب HTTP GET باستخدام fetch:
النمط المضاد
// ❌ استخدام دوال مجهولة مضمنة 💩fetch(url) .then(response => response.status < 400 ? response : Promise.reject(new Error('Request Failed: ' + response.ststus))) .then(response => response.text())الحل: دوال مسماة
// ✅ الوضوح يظهر: دوال مسماةfetch(url) .then(checkResponse) .then(getText)
// دوال عامة قابلة لإعادة الاستخدامfunction checkResponse(response) { return response.status < 400 ? response : Promise.reject(new Error('Request Failed: ' + response.ststus))}function getText(response) { return response.text()}فوائد هذا الأسلوب تزداد وضوحًا كلما أصبح كودك أكثر جفافًا (DRY).
موارد إضافية: شاهد فيديوهاتي القصيرة (دقيقة واحدة) عن التسجيل الأساسي والتصحيح المتقدم باستخدام هذه التقنية.
#2: غرض واحد (الدوال)
يبدو الأمر خادعًا في دقته: غرض واحد.
لكنه في الواقع ذاتي، تعسفي، وأحيانًا بلا معنى.
المثير للاهتمام أن معظم المطورين يذكرون أنهم جيدون جدًا في تطبيق مبدأ الغرض الواحد على كودهم. وليس منفصلاً عن ذلك: فهم يذكرون أنهم سائقون ممتازون أيضًا!
لنلقِ نظرة على مثال يذكره (الموهوب للغاية) Jake Archibald في مقالته عن async/await على موقع Google Developers (ملاحظة: 2024، تمت إزالة الرابط).
// source: https://developers.google.com/web/fundamentals/primers/async-functionsfunction logInOrder(urls) { // fetch all the URLs const textPromises = urls.map(url => { return fetch(url).then(response => response.text()); });
// log them in order textPromises.reduce((chain, textPromise) => { return chain.then(() => textPromise) .then(text => console.log(text)); }, Promise.resolve());}غرض واحد؟
أقول لا. ما الذي تفعله logInOrder؟
- التكرار عبر قائمة من
urls - تطبيقها على طلب HTTP GET مضمّن:
fetchعبر HTTP- إرجاع نص الاستجابة
- إلحاق
.then(text => console.log(text))بعد كل وعد فيtextPromise - طباعة النتائج بشكل تسلسلي
هناك 5 دوال مجهولة مُعرّفة في هذه الدالة الواحدة. وكما يشير Jake حتى، فإن .reduce معقدة جدًا. ليس من المنطقي كتابة آليات دقيقة يدويًا في جميع أنحاء الكود. بعبارة أخرى، نحن لا نكتب كود إنشاء DOM باستخدام document.createElement() و element.setAttribute() إلى ما لا نهاية. بدلاً من ذلك، نختار أفضل أداة من بين العديد من الخيارات: دوال مساعدة/أدوات مساعدة، مكتبات أو أطر عمل.
الحل: دوال ذات غرض واحد
ابدأ باستخراج الدوال…

ثم استبدل .reduce() و logPromise() بـ Promise.all و ..map()…

الخلاصة
جرّب تطبيق هذه التقنيات على كودك الخاص! ثم غرد لي وأخبرني كيف سارت الأمور. أو إذا كانت لديك أسئلة أو تعليقات، تواصل معي أيضًا!
ساعد في نشر #PromiseTruth وشارك هذه المقالة. ❤️
